| /* | |
| * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * @test | |
| * @bug 4406815 8222969 8266784 | |
| * @summary RuleBasedCollatorTest uses very limited but selected test data | |
| * to test basic functionalities provided by RuleBasedCollator. | |
| * @run testng/othervm RuleBasedCollatorTest | |
| */ | |
| import java.text.CollationElementIterator; | |
| import java.text.CollationKey; | |
| import java.text.RuleBasedCollator; | |
| import java.text.Collator; | |
| import java.text.ParseException; | |
| import java.util.Arrays; | |
| import java.util.Locale; | |
| import org.testng.annotations.BeforeClass; | |
| import org.testng.annotations.DataProvider; | |
| import org.testng.annotations.Test; | |
| import org.testng.SkipException; | |
| import static org.testng.Assert.*; | |
| public class RuleBasedCollatorTest { | |
| static RuleBasedCollator USC; | |
| static String US_RULES; | |
| @BeforeClass | |
| public void setup() { | |
| Collator c = Collator.getInstance(Locale.US); | |
| if (!(c instanceof RuleBasedCollator)) { | |
| throw new SkipException("skip tests."); | |
| } | |
| USC = (RuleBasedCollator) c; | |
| US_RULES = USC.getRules(); | |
| } | |
| @DataProvider(name = "rulesData") | |
| Object[][] rulesData() { | |
| //Basic Tailor | |
| String BASIC_TAILOR_RULES = "< b=c<\u00e6;A,a"; | |
| String[] BASIC_TAILOR_DATA = {"\u00e6", "b", "a", "c", "A"}; | |
| String[] BASIC_TAILOR_EXPECTED = {"b", "c", "\u00e6", "A", "a"}; | |
| //Contraction | |
| String CONTRACTION_RULES = US_RULES + "& b < ch ,cH, Ch, CH < c "; | |
| String[] CONTRACTION_DATA = {"b", "c", "ch", "CH", "Ch", "cH"}; | |
| String[] CONTRACTION_EXPECTED = {"b", "ch", "cH", "Ch", "CH", "c"}; | |
| //Expansion | |
| String EXPANSION_RULES = US_RULES + "& ae = \u00e4 < b"; | |
| String[] EXPANSION_DATA = {"ad", "af", "\u00e4"}; | |
| String[] EXPANSION_EXPECTED = {"ad", "\u00e4", "af"}; | |
| //Punctuation | |
| String PUNCTUATION_RULES = US_RULES + "< ' ' < '-'"; | |
| String[] PUNCTUATION_DATA = {"b-w", "b-W", "B-w", "B-W", "bW", "bw", | |
| "Bw", "BW", "b w", "b W", "B w", "B W"}; | |
| String[] PUNCTUATION_EXPECTED = {"bw", "bW", "Bw", "BW", "b w", "b W", | |
| "B w", "B W", "b-w", "b-W", "B-w", "B-W"}; | |
| return new Object[][] { | |
| {BASIC_TAILOR_RULES, BASIC_TAILOR_DATA, BASIC_TAILOR_EXPECTED}, | |
| {CONTRACTION_RULES, CONTRACTION_DATA, CONTRACTION_EXPECTED}, | |
| {EXPANSION_RULES, EXPANSION_DATA, EXPANSION_EXPECTED}, | |
| {PUNCTUATION_RULES, PUNCTUATION_DATA, PUNCTUATION_EXPECTED} | |
| }; | |
| } | |
| @Test(dataProvider = "rulesData") | |
| public void testRules(String rules, String[] testData, String[] expected) | |
| throws ParseException { | |
| Arrays.sort(testData, new RuleBasedCollator(rules)); | |
| assertEquals(testData, expected); | |
| } | |
| @DataProvider(name = "FrenchSecondarySort") | |
| Object[][] FrenchSecondarySort() { | |
| return new Object[][] { | |
| { "\u0061\u00e1\u0061", "\u00e1\u0061\u0061", 1 }, | |
| //{"\u0061\u00e1", "\u00e1\u0041", 1}, //JDK-4406815 | |
| //{"\u00e1\u0041", "\u0061\u00e1", -1}, //JDK-4406815 | |
| {"\u1ea0a", "\u1ea2A", -1}, //case ignore | |
| { "\u1ea0b", "\u1ea2A", 1 }, //primary overwrite | |
| { "\u1e15", "\u1e1d", -1 }, //ignore sec diacritic | |
| { "a", "\u1ea1", -1 } }; | |
| } | |
| @Test(dataProvider = "FrenchSecondarySort") | |
| public void testFrenchSecondarySort(String sData, String tData, | |
| int expected) throws ParseException { | |
| String french_rule = "@"; | |
| String rules = US_RULES + french_rule; | |
| RuleBasedCollator rc = new RuleBasedCollator(rules); | |
| int result = rc.compare(sData, tData); | |
| assertEquals(expected, result); | |
| } | |
| @DataProvider(name = "ThaiLaoVowelConsonantSwapping") | |
| Object[][] ThaiLaoVowelConsonantSwapping() { | |
| return new Object[][] {{"\u0e44\u0e01", "\u0e40\u0e2e", -1},//swap | |
| {"\u0e2e\u0e40", "\u0e01\u0e44", 1},//no swap | |
| {"\u0e44\u0061", "\u0e40\u0081", 1}//no swap | |
| }; | |
| } | |
| @Test(dataProvider = "ThaiLaoVowelConsonantSwapping") | |
| public void testThaiLaoVowelConsonantSwapping(String sData, String tData, | |
| int expected) throws ParseException { | |
| String thai_rule = "& Z < \u0e01 < \u0e2e <\u0e40 < \u0e44!"; | |
| String rules = US_RULES + thai_rule; | |
| RuleBasedCollator rc = new RuleBasedCollator(rules); | |
| int result = rc.compare(sData, tData); | |
| assertEquals(expected, result); | |
| } | |
| @Test | |
| public void testIgnorableCharacter() throws ParseException { | |
| String rule = "=f<a<c"; | |
| RuleBasedCollator rc = new RuleBasedCollator(rule); | |
| CollationElementIterator iter = rc.getCollationElementIterator("f"); | |
| int element = iter.next(); | |
| int primary = iter.primaryOrder(element); | |
| assertEquals(primary, 0); | |
| } | |
| @DataProvider(name = "Normalization") | |
| Object[][] Normalization() { | |
| return new Object[][] { | |
| //micro sign has no canonical decomp mapping | |
| // 0:NO_Decomposition; | |
| // 1:CANONICAL_Decomposition; | |
| // 2:FULL_Decomposition | |
| {"\u00b5", "\u03BC", 0, -1}, | |
| {"\u00b5", "\u03BC", 1, -1}, | |
| {"\u00b5", "\u03BC", 2, 0} | |
| }; | |
| } | |
| @Test(dataProvider = "Normalization") | |
| public void testNormalization(String sData, String tData, int decomp, | |
| int result) { | |
| RuleBasedCollator rc = (RuleBasedCollator)USC.clone(); | |
| rc.setDecomposition(decomp); | |
| assertEquals(rc.compare(sData, tData), result); | |
| } | |
| @Test | |
| public void testEquality() throws ParseException { | |
| String rule1 = "<a=b"; | |
| RuleBasedCollator rc1= new RuleBasedCollator(rule1); | |
| //test equals() | |
| assertTrue(rc1.equals(new RuleBasedCollator(rule1))); | |
| //test semantic equality | |
| String[] array1 = {"b", "c", "a"}; | |
| String[] array2 = Arrays.copyOf(array1, array1.length); | |
| String[] expected = {"b", "a", "c"}; | |
| String rule2 = "<b=a"; | |
| RuleBasedCollator rc2= new RuleBasedCollator(rule2); | |
| Arrays.sort(array1, rc1); | |
| Arrays.sort(array2, rc2); | |
| assertEquals(array1, array2); | |
| assertEquals(array1, expected); | |
| } | |
| @Test | |
| public void testBasicParsingOrder() throws ParseException { | |
| String rule1 = "< a < b & a < c"; | |
| String rule2 = "< a < c & a < b"; | |
| String rule3 = "< a < b < c"; | |
| String s = "abc"; | |
| RuleBasedCollator c1 = new RuleBasedCollator(rule1); | |
| RuleBasedCollator c2 = new RuleBasedCollator(rule2); | |
| RuleBasedCollator c3 = new RuleBasedCollator(rule3); | |
| CollationKey k1 = c1.getCollationKey(s); | |
| CollationKey k2 = c2.getCollationKey(s); | |
| CollationKey k3 = c3.getCollationKey(s); | |
| //rule1 should not equals to rule2 | |
| assertEquals(k1.compareTo(k2) == 0, false); | |
| //rule2 should equals to rule3 | |
| assertEquals(k2.compareTo(k3) == 0, true); | |
| } | |
| @DataProvider(name = "ParseData") | |
| Object[][] ParseData() { | |
| return new Object[][] { | |
| {""}, | |
| {"a < b"}, | |
| {"< a-b < c"}, | |
| {"< ,a"}, | |
| {"< a < b & c < d"} | |
| }; | |
| } | |
| @Test(dataProvider = "ParseData", | |
| expectedExceptions = ParseException.class) | |
| public void testParseException(String rule) throws ParseException{ | |
| new RuleBasedCollator(rule); | |
| } | |
| @Test(expectedExceptions = NullPointerException.class) | |
| public void testNullParseException() throws ParseException{ | |
| new RuleBasedCollator(null); | |
| } | |
| } |