summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Chang <vichang@google.com>2021-06-10 01:01:55 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-06-10 01:01:55 +0000
commit04ef3b3e04110865592d8e50b90ae0bcd7e05402 (patch)
treec21227d1efbcfdb01f5af8147135717fdeb7553e
parent312d9b5ea9e0b4ae192e87ed829fd086e44418d3 (diff)
parent0c81908df2f0f05fa97232a1f49d7c029cd417b3 (diff)
downloadicu-04ef3b3e04110865592d8e50b90ae0bcd7e05402.tar.gz
Add API coverage for @IntraCoreApi provided by ICU am: 0c81908df2
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/icu/+/14919654 Change-Id: If06a2d68216a469be6aa26b1f417f7565cefbee4
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/system/AppSpecializationHooksTest.java14
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/system/ZygoteHooksTest.java42
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java136
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java30
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/charset/CharsetFactoryTest.java47
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/text/CompatibleDecimalFormatFactoryTest.java66
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/text/ExtendedDecimalFormatSymbolsTest.java45
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/text/ExtendedIDNATest.java98
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/text/ExtendedTimeZoneNamesTest.java123
-rw-r--r--android_icu4j/testing/src/com/android/icu/test/util/regex/MatcherNativeTest.java26
10 files changed, 626 insertions, 1 deletions
diff --git a/android_icu4j/testing/src/com/android/i18n/test/system/AppSpecializationHooksTest.java b/android_icu4j/testing/src/com/android/i18n/test/system/AppSpecializationHooksTest.java
index 2a57bf0aa..0167bffaf 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/system/AppSpecializationHooksTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/system/AppSpecializationHooksTest.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertNull;
import android.icu.testsharding.MainTestShard;
+import com.android.i18n.system.AppSpecializationHooks;
import com.android.i18n.system.ZygoteHooks;
import org.junit.Test;
@@ -33,7 +34,18 @@ public class AppSpecializationHooksTest {
@Test
public void testDisableCompatChangesBeforeAppStart() {
- // CtsIcuTestCases use current SDK, and thus the property value should be null.
+ assertSystemPropBinaryDataPath_null();
+
+ // The value should stay null after the app startup or after invoking the same method
+ // repeatedly.
+ AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();
+ assertSystemPropBinaryDataPath_null();
+ }
+
+ /**
+ * CtsIcuTestCases use current SDK, and thus the property value should be null.
+ */
+ private static void assertSystemPropBinaryDataPath_null() {
assertNull(ZygoteHooks.PROP_ICUBINARY_DATA_PATH + " property is not null.",
System.getProperty(ZygoteHooks.PROP_ICUBINARY_DATA_PATH));
}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/system/ZygoteHooksTest.java b/android_icu4j/testing/src/com/android/i18n/test/system/ZygoteHooksTest.java
new file mode 100644
index 000000000..6bc2ec20d
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/i18n/test/system/ZygoteHooksTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.i18n.test.system;
+
+import android.icu.testsharding.MainTestShard;
+
+import com.android.i18n.system.ZygoteHooks;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class ZygoteHooksTest {
+
+ /**
+ * Invoke the {@link ZygoteHooks} preload methods in tests to add API coverage. Invoking methods
+ * shouldn't have any visible changes, but preloading some objects into the internal ICU4J
+ * caches.
+ */
+ @Test
+ public void testPreload() {
+ ZygoteHooks.onBeginPreload();
+ ZygoteHooks.onEndPreload();
+ }
+
+}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
index 179b799dc..17d823cce 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
@@ -22,7 +22,14 @@ import android.icu.testsharding.MainTestShard;
import com.android.i18n.timezone.WallTime;
import com.android.i18n.timezone.ZoneInfoData;
import com.android.i18n.timezone.ZoneInfoDb;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.io.Serializable;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.time.Instant;
@@ -176,6 +183,50 @@ public class ZoneInfoDataTest extends TestCase {
// Even a millisecond before a transition means that the transition is not active.
Instant beforeTransitionTime = transitionTime.minusMillis(1);
assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), beforeTransitionTime);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), offsetFromSeconds(0),
+ beforeTransitionTime);
+ assertInDaylightTime(zoneInfoData, beforeTransitionTime, false);
+
+ // A time equal to the transition point activates the transition.
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), transitionTime);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), offsetFromSeconds(1800),
+ transitionTime);
+ assertInDaylightTime(zoneInfoData, transitionTime, true);
+
+ // A time after the transition point but before the next activates the transition.
+ Instant afterTransitionTime = transitionTime.plusMillis(1);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), afterTransitionTime);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), offsetFromSeconds(1800),
+ afterTransitionTime);
+ assertInDaylightTime(zoneInfoData, afterTransitionTime, true);
+
+ assertNoDSTSavings(zoneInfoData, timeFromSeconds(5400));
+ assertRawOffset(zoneInfoData, offsetFromSeconds(5400));
+ }
+
+ /**
+ * Tests {@link ZoneInfoData#createInstance}, and checks to make sure that rounding the time from
+ * milliseconds to seconds does not cause issues around the boundary of positive transitions.
+ */
+ public void testCreateInstance() throws Exception {
+ long[][] transitions = {
+ { 0, 0 },
+ { 5, 1 },
+ { 2000, 2 },
+ };
+ int[][] types = {
+ { 1800, 0 },
+ { 3600, 1 },
+ { 5400, 0 }
+ };
+ ZoneInfoData zoneInfoData = createInstance(transitions, types);
+ assertArrayEquals(new long[] { 0, 5, 2000 }, zoneInfoData.getTransitions());
+
+ Instant transitionTime = timeFromSeconds(5);
+
+ // Even a millisecond before a transition means that the transition is not active.
+ Instant beforeTransitionTime = transitionTime.minusMillis(1);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), beforeTransitionTime);
assertInDaylightTime(zoneInfoData, beforeTransitionTime, false);
// A time equal to the transition point activates the transition.
@@ -658,6 +709,63 @@ public class ZoneInfoDataTest extends TestCase {
zoneInfoData.hasSameRules(copyWithDiffOffset));
}
+ public void testSerialization() throws IOException, ClassNotFoundException {
+ String tzId = TestSerialization.TZID;
+ ZoneInfoData zone = ZoneInfoDb.getInstance().makeZoneInfoData(tzId);
+ assertNotNull(zone);
+ TestSerialization testObj = new TestSerialization(zone);
+
+ final byte[] data;
+ try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+ oos.writeObject(testObj);
+ data = baos.toByteArray();
+ }
+
+ final TestSerialization newTestObj;
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
+ newTestObj = (TestSerialization) ois.readObject();
+ }
+
+ assertEquals(zone, newTestObj.data);
+ assertEquals(testObj, newTestObj);
+ }
+
+ private static class TestSerialization implements Serializable {
+
+ private static final String TZID = "Europe/London";
+
+ private static final ObjectStreamField[] serialPersistentFields =
+ ZoneInfoData.ZONEINFO_SERIALIZED_FIELDS;
+
+ private ZoneInfoData data;
+
+ private TestSerialization(ZoneInfoData data) {
+ this.data = data;
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ ObjectInputStream.GetField getField = in.readFields();
+ data = ZoneInfoData.createFromSerializationFields(TZID, getField);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ ObjectOutputStream.PutField putField = out.putFields();
+ data.writeToSerializationFields(putField);
+ out.writeFields();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TestSerialization)) {
+ return false;
+ }
+
+ return data.equals(((TestSerialization) obj).data);
+ }
+ }
+
private static void assertRawOffset(ZoneInfoData zoneInfoData, Duration expectedOffset) {
assertEquals(expectedOffset.toMillis(), zoneInfoData.getRawOffset());
}
@@ -686,6 +794,17 @@ public class ZoneInfoDataTest extends TestCase {
}
}
+ private static void assertOffsetAt( ZoneInfoData zoneInfoData, Duration expectedStandardOffset,
+ Duration expectedDstOffset, Instant... times) {
+ int[] offsets = new int[2];
+ for (Instant time : times) {
+ zoneInfoData.getOffsetsByUtcTime(time.toEpochMilli(), offsets);
+ assertEquals("Unexpected standard offset at " + time,
+ expectedStandardOffset.toMillis(), offsets[0]);
+ assertEquals("Unexpected Dst offset at " + time, expectedDstOffset.toMillis(), offsets[1]);
+ }
+ }
+
private static Instant timeFromSeconds(long timeInSeconds) {
return Instant.ofEpochSecond(timeInSeconds);
}
@@ -724,6 +843,23 @@ public class ZoneInfoDataTest extends TestCase {
return ZoneInfoData.readTimeZone("TimeZone for '" + name + "'", bufferIterator);
}
+ private ZoneInfoData createInstance(long[][] transitionMap, int[][] typeMap) {
+ long[] transitions = new long[transitionMap.length];
+ byte[] types = new byte[transitionMap.length];
+ for (int i = 0; i < transitionMap.length; ++i) {
+ transitions[i] = transitionMap[i][0];
+ types[i] = (byte) transitionMap[i][1];
+ }
+ int[] offsets = new int[typeMap.length];
+ boolean[] isDsts = new boolean[typeMap.length];
+ for (int i = 0; i < typeMap.length; ++i) {
+ offsets[i] = typeMap[i][0];
+ isDsts[i] = (typeMap[i][1] != 0);
+ }
+
+ return ZoneInfoData.createInstance(getName(), transitions, types, offsets, isDsts);
+ }
+
/**
* Creates {@code typeCount} "types" for use with
* {@link ZoneInfoTestHelper.ZicDataBuilder#setTypes(int[][])} and related methods. Each type is
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
index efc7c85e1..27f818a5b 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
@@ -16,6 +16,9 @@
package com.android.i18n.test.timezone;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+
import android.icu.testsharding.MainTestShard;
import com.android.i18n.timezone.TimeZoneDataFiles;
@@ -24,6 +27,11 @@ import com.android.i18n.timezone.ZoneInfoDb;
import java.io.File;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import libcore.timezone.testing.ZoneInfoTestHelper;
@MainTestShard
@@ -99,6 +107,28 @@ public class ZoneInfoDbTest extends junit.framework.TestCase {
}
}
+ public void testGetAvailableIDsWithRawOffset() {
+ ZoneInfoDb zoneInfoDb = ZoneInfoDb.getInstance();
+ String[] allIds = zoneInfoDb.getAvailableIDs();
+ List<ZoneInfoData> allZones = Arrays.stream(allIds)
+ .map(id -> zoneInfoDb.makeZoneInfoData(id))
+ .collect(toList());
+
+ int[] allRawOffsets = allZones.stream()
+ .mapToInt(zone -> zone.getRawOffset())
+ .distinct()
+ .toArray();
+
+ for (int rawOffset : allRawOffsets) {
+ Set<String> ids = new HashSet<>(Arrays.asList(zoneInfoDb.getAvailableIDs(rawOffset)));
+ Set<String> expectedIds = allZones.stream()
+ .filter(zone -> zone.getRawOffset() == rawOffset)
+ .map(zone -> zone.getID())
+ .collect(toSet());
+ assertEquals("zoneInfoDb.getAvailableIDs(" + rawOffset + ")", expectedIds, ids);
+ }
+ }
+
public void testLoadTzData_badHeader() throws Exception {
RandomAccessFile in = new RandomAccessFile(TZDATA_FILE, "r");
byte[] content = new byte[(int) in.length()];
diff --git a/android_icu4j/testing/src/com/android/icu/test/charset/CharsetFactoryTest.java b/android_icu4j/testing/src/com/android/icu/test/charset/CharsetFactoryTest.java
new file mode 100644
index 000000000..121c01c89
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/icu/test/charset/CharsetFactoryTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.icu.test.charset;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.icu.testsharding.MainTestShard;
+
+import com.android.icu.charset.CharsetFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.nio.charset.Charset;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class CharsetFactoryTest {
+
+ @Test
+ public void testCreate() {
+ for (String name : CharsetFactory.getAvailableCharsetNames()) {
+ String msg = "Charset: " + name;
+ Charset charset = CharsetFactory.create(name);
+ assertNotNull(msg, charset);
+
+ assertNotNull(msg, charset.newEncoder());
+ assertNotNull(msg, charset.newDecoder());
+ }
+ }
+
+}
diff --git a/android_icu4j/testing/src/com/android/icu/test/text/CompatibleDecimalFormatFactoryTest.java b/android_icu4j/testing/src/com/android/icu/test/text/CompatibleDecimalFormatFactoryTest.java
new file mode 100644
index 000000000..84cfc66e4
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/icu/test/text/CompatibleDecimalFormatFactoryTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.icu.test.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.icu.testsharding.MainTestShard;
+import android.icu.text.DecimalFormat;
+import android.icu.text.DecimalFormatSymbols;
+import android.icu.text.NumberFormat;
+import android.icu.util.ULocale;
+
+import com.android.icu.text.CompatibleDecimalFormatFactory;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.text.ParseException;
+import java.text.ParsePosition;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class CompatibleDecimalFormatFactoryTest {
+ @Test
+ public void testCreate() throws ParseException {
+ ULocale locale = ULocale.US;
+ String pattern = NumberFormat.getPatternForStyle(locale, NumberFormat.NUMBERSTYLE);
+ assertNotNull(pattern);
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
+ DecimalFormat decimalFormat = CompatibleDecimalFormatFactory.create(pattern, dfs);
+
+ double value = 1234.56;
+ String formatted = decimalFormat.format(value);
+ assertEquals("1,234.56", formatted);
+
+ Number parsed = decimalFormat.parse(formatted);
+ assertEquals(value, parsed.doubleValue(), 0.01);
+
+
+ ParsePosition parsePosition = new ParsePosition(0);
+ // Parsing with a leading space should return error
+ decimalFormat.parse(" 1,234.56", parsePosition);
+ assertEquals(2, parsePosition.getIndex());
+
+ parsePosition = new ParsePosition(0);
+ // Parsing with a bidi character should not be parsed properly
+ decimalFormat.parse("1,\u200e234.56", parsePosition);
+ assertEquals(1, parsePosition.getIndex());
+ }
+}
diff --git a/android_icu4j/testing/src/com/android/icu/test/text/ExtendedDecimalFormatSymbolsTest.java b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedDecimalFormatSymbolsTest.java
new file mode 100644
index 000000000..f19eb4aee
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedDecimalFormatSymbolsTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.icu.test.text;
+
+import static org.junit.Assert.assertEquals;
+
+import android.icu.testsharding.MainTestShard;
+import android.icu.text.NumberingSystem;
+import android.icu.util.ULocale;
+
+import com.android.icu.text.ExtendedDecimalFormatSymbols;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class ExtendedDecimalFormatSymbolsTest {
+ @Test
+ public void testGetLocalizedPatternSeparator() {
+ ExtendedDecimalFormatSymbols edfs;
+
+ edfs = ExtendedDecimalFormatSymbols.getInstance(ULocale.US, NumberingSystem.LATIN);
+ assertEquals(";", edfs.getLocalizedPatternSeparator());
+
+ edfs = ExtendedDecimalFormatSymbols.getInstance(new ULocale("sv"),
+ NumberingSystem.getInstanceByName("arab"));
+ assertEquals("؛", edfs.getLocalizedPatternSeparator());
+ }
+}
diff --git a/android_icu4j/testing/src/com/android/icu/test/text/ExtendedIDNATest.java b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedIDNATest.java
new file mode 100644
index 000000000..a9998fc7a
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedIDNATest.java
@@ -0,0 +1,98 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.icu.test.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.icu.testsharding.MainTestShard;
+import android.icu.text.IDNA;
+import android.icu.text.StringPrepParseException;
+
+import com.android.icu.text.ExtendedIDNA;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class ExtendedIDNATest {
+
+ @Test
+ public void testConvertIDNToASCII() throws StringPrepParseException {
+ try {
+ toASCII("www.m\uE400kitorppa.edu", 0);
+ fail("should throw StringPrepParseException");
+ } catch (StringPrepParseException e) {
+ // expected
+ }
+
+ try {
+ toASCII("www.\u672C\uFE73\uFFFF.jp", 0);
+ fail("should throw StringPrepParseException");
+ } catch (StringPrepParseException e) {
+ // expected
+ }
+
+ assertEquals("www.xn--gwtq9nb2a.jp", toASCII(
+ "www.\u65E5\u672C\u5E73.jp", 0));
+ assertEquals("www.xn--vckk7bxa0eza9ezc9d.com",
+ toASCII("www.\u30CF\u30F3\u30C9\u30DC\u30FC\u30EB\u30B5\u30E0\u30BA.com",0));
+ assertEquals("www.xn--frgbolaget-q5a.nu", toASCII(
+ "www.f\u00E4rgbolaget.nu", IDNA.ALLOW_UNASSIGNED));
+ assertEquals("www.xn--bcher-kva.de", toASCII("www.b\u00FCcher.de", IDNA.ALLOW_UNASSIGNED));
+ assertEquals("www.google.com", toASCII("www.google\u002Ecom", IDNA.USE_STD3_RULES));
+ }
+
+ private static String toASCII(String str, int flags) throws StringPrepParseException {
+ return ExtendedIDNA.convertIDNToASCII(str, flags).toString();
+ }
+
+ @Test
+ public void testConvertIDNToUnicode() throws StringPrepParseException {
+ try {
+ ExtendedIDNA.convertIDNToUnicode(null, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ assertEquals("", toUnicode("", 0));
+ assertEquals("www.bcher.de", toUnicode("www.bcher.de", 0));
+ assertEquals("www.b\u00FCcher.de", toUnicode("www.b\u00FCcher.de", 0));
+ assertEquals("www.\u65E5\u672C\u5E73.jp", toUnicode("www.\u65E5\u672C\u5E73.jp", 0));
+ assertEquals("www\uff0e\u65E5\u672C\u5E73\uff61jp",
+ toUnicode("www\uFF0Exn--gwtq9nb2a\uFF61jp", 0));
+ assertEquals("www.\u65E5\u672C\u5E73.jp", toUnicode("www.xn--gwtq9nb2a.jp", 0));
+ assertEquals("", toUnicode("", IDNA.ALLOW_UNASSIGNED));
+ assertEquals("www.f\u00E4rgbolaget.nu", toUnicode(
+ "www.f\u00E4rgbolaget.nu", IDNA.USE_STD3_RULES));
+ assertEquals("www.r\u00E4ksm\u00F6rg\u00E5s\u3002nu", toUnicode(
+ "www.r\u00E4ksm\u00F6rg\u00E5s\u3002nu",
+ IDNA.USE_STD3_RULES));
+ // RI bug. It cannot parse "www.xn--gwtq9nb2a.jp" when
+ // USE_STD3_ASCII_RULES is set.
+ assertEquals("www\uff0e\u65E5\u672C\u5E73\uff61jp",
+ toUnicode("www\uFF0Exn--gwtq9nb2a\uFF61jp", IDNA.USE_STD3_RULES));
+
+ }
+
+ private static String toUnicode(String str, int flags) throws StringPrepParseException {
+ return ExtendedIDNA.convertIDNToUnicode(str, flags).toString();
+ }
+}
diff --git a/android_icu4j/testing/src/com/android/icu/test/text/ExtendedTimeZoneNamesTest.java b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedTimeZoneNamesTest.java
new file mode 100644
index 000000000..111ef89a9
--- /dev/null
+++ b/android_icu4j/testing/src/com/android/icu/test/text/ExtendedTimeZoneNamesTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.icu.test.text;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.icu.testsharding.MainTestShard;
+import android.icu.text.TimeZoneNames;
+import android.icu.util.ULocale;
+
+import com.android.icu.text.ExtendedTimeZoneNames;
+import com.android.icu.text.ExtendedTimeZoneNames.Match;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@MainTestShard
+@RunWith(JUnit4.class)
+public class ExtendedTimeZoneNamesTest {
+
+ private static final String LONDON_TZID = "Europe/London";
+ private static final String LOS_ANGELES_TZID = "America/Los_Angeles";
+ private static final String VANCOUVER_TZID = "America/Vancouver";
+
+ @Test
+ public void testMatchName_preferCurrentTzId() {
+ assertMatchName(ULocale.US, "PST", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, false);
+ assertMatchName(ULocale.US, "PDT", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, true);
+ assertMatchName(ULocale.US, "Pacific Standard Time", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, false);
+ assertMatchName(ULocale.US, "Pacific Daylight Time", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, true);
+
+ // current tz id is preferred even though the locale country is different.
+ assertMatchName(ULocale.UK, "Pacific Standard Time", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, false);
+ assertMatchName(ULocale.CANADA, "Pacific Standard Time", LOS_ANGELES_TZID,
+ LOS_ANGELES_TZID, false);
+ assertMatchName(ULocale.US, "Pacific Standard Time", VANCOUVER_TZID,
+ VANCOUVER_TZID, false);
+ }
+
+ @Test
+ public void testMatchName_shouldGuessTimeZoneForLocaleCounty() {
+ // Guess the time zone from the locale country.
+ assertMatchName(ULocale.CANADA, "Pacific Standard Time", LONDON_TZID,
+ VANCOUVER_TZID, false);
+ }
+
+ @Test
+ public void testMatchName_withStartOffset() {
+ String ignored = "IGNORED_STR";
+ assertMatchName(ULocale.US, ignored + "Pacific Standard Time", ignored.length(),
+ LOS_ANGELES_TZID, LOS_ANGELES_TZID, false, "Pacific Standard Time".length());
+ assertNullMatch(ULocale.US, ignored + "Pacific Standard Time", /*start=*/ 0,
+ LOS_ANGELES_TZID);
+ }
+
+ @Test
+ public void testMatchName_withDifferentLocales() {
+ long date = 1609459200000L; // 1 January 2021 00:00:00 GMT+00:00
+
+ // Test some locales
+ for (ULocale locale : ULocale.getAvailableLocales()) {
+ ExtendedTimeZoneNames extendedTimeZoneNames = ExtendedTimeZoneNames.getInstance(locale);
+ String name = extendedTimeZoneNames.getTimeZoneNames().getDisplayName(LOS_ANGELES_TZID,
+ TimeZoneNames.NameType.LONG_STANDARD, date);
+
+ // Skip this locale if the name is not available.
+ if (name == null) {
+ continue;
+ }
+ assertMatchName(locale, name, LOS_ANGELES_TZID, LOS_ANGELES_TZID, false);
+ }
+ }
+
+ private static void assertMatchName(ULocale locale, String input, int start, String currentTzId,
+ String expectedTzId, boolean isDst, int expectedNameLength) {
+ String msg = "locale: " + locale + " input: " + input;
+ ExtendedTimeZoneNames timeZoneNames = ExtendedTimeZoneNames.getInstance(locale);
+ Match match = timeZoneNames.matchName(input, start, currentTzId);
+ assertNotNull(msg, match);
+ assertEquals(msg, expectedTzId, match.getTzId());
+ assertEquals(msg, isDst, match.isDst());
+ assertEquals(msg, expectedNameLength, match.getMatchLength());
+ }
+
+ private static void assertMatchName(ULocale locale, String input, String currentTzId,
+ String expectedTzId, boolean isDst, int expectedNameLength) {
+ assertMatchName(locale, input, 0, currentTzId, expectedTzId, isDst, expectedNameLength);
+ }
+
+ private static void assertMatchName(ULocale locale, String input, String currentTzId,
+ String expectedTzId, boolean isDst) {
+ assertMatchName(locale, input, currentTzId, expectedTzId, isDst, input.length());
+ }
+
+ private static void assertNullMatch(ULocale locale, String input, int start,
+ String currentTzId) {
+ String msg = "locale: " + locale + " input: " + input;
+ ExtendedTimeZoneNames timeZoneNames = ExtendedTimeZoneNames.getInstance(locale);
+ assertNull(msg, timeZoneNames.matchName(input, start, currentTzId));
+ }
+}
diff --git a/android_icu4j/testing/src/com/android/icu/test/util/regex/MatcherNativeTest.java b/android_icu4j/testing/src/com/android/icu/test/util/regex/MatcherNativeTest.java
index 0c8e84e81..4121362f0 100644
--- a/android_icu4j/testing/src/com/android/icu/test/util/regex/MatcherNativeTest.java
+++ b/android_icu4j/testing/src/com/android/icu/test/util/regex/MatcherNativeTest.java
@@ -164,6 +164,14 @@ public class MatcherNativeTest {
return matcherNative.hitEnd();
}
+ public boolean requireEnd() {
+ return matcherNative.requireEnd();
+ }
+
+ public boolean lookingAt() {
+ return matcherNative.lookingAt(groups);
+ }
+
public String group() {
return group(0);
}
@@ -213,6 +221,24 @@ public class MatcherNativeTest {
}
@Test
+ public void testLookingAt() {
+ Pattern p = Pattern.compile("abc");
+ Matcher m = p.matcher("aabc");
+ assertTrue(m.find());
+
+ m.reset();
+ assertFalse(m.lookingAt());
+ }
+
+ @Test
+ public void testRequireEnd() {
+ Pattern p = Pattern.compile("abc$");
+ Matcher m = p.matcher("abc");
+ assertTrue(m.find());
+ assertTrue(m.requireEnd());
+ }
+
+ @Test
public void testResetCharSequence() {
Pattern p = Pattern.compile("abcd");
Matcher m = p.matcher("abcd");