diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2021-06-09 13:34:40 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-06-09 13:34:40 +0000 |
commit | 3f05414d60f10d7fb3daaef4e4121f4b8593aeea (patch) | |
tree | 790f0203bca21b744a59a889c0f759b4e2bd9fea /android_icu4j | |
parent | b9150ba817f84d725059780af42289e56a7c8be6 (diff) | |
parent | c9e5a7e14b312df949dcf8008134d58fa9adcd3f (diff) | |
download | icu-3f05414d60f10d7fb3daaef4e4121f4b8593aeea.tar.gz |
Merge "Add API coverage for @IntraCoreApi provided by ICU"
Diffstat (limited to 'android_icu4j')
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"); |