1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html#License
3/*
4 *******************************************************************************
5 * Copyright (C) 2002-2014, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 *******************************************************************************
8 */
9
10/**
11 * Port From:   ICU4C v2.1 : collate/CollationMonkeyTest
12 * Source File: $ICU4CRoot/source/test/intltest/mnkytst.cpp
13 **/
14
15package com.ibm.icu.dev.test.collator;
16
17import java.util.Locale;
18import java.util.Random;
19
20import org.junit.Test;
21
22import com.ibm.icu.dev.test.TestFmwk;
23import com.ibm.icu.text.CollationKey;
24import com.ibm.icu.text.Collator;
25import com.ibm.icu.text.RuleBasedCollator;
26
27/**
28 * CollationMonkeyTest is a third level test class.  This tests the random
29 * substrings of the default test strings to verify if the compare and
30 * sort key algorithm works correctly.  For example, any string is always
31 * less than the string itself appended with any character.
32 */
33
34public class CollationMonkeyTest extends TestFmwk {
35
36    private String source = "-abcdefghijklmnopqrstuvwxyz#&^$@";
37
38    @Test
39    public void TestCollationKey() {
40        if(source.length() == 0) {
41            errln("CollationMonkeyTest.TestCollationKey(): source is empty - ICU_DATA not set or data missing?");
42            return;
43        }
44        Collator myCollator;
45        try {
46             myCollator = Collator.getInstance(new Locale("en", "US"));
47        } catch (Exception e) {
48            warnln("ERROR: in creation of collator of ENGLISH locale");
49            return;
50        }
51
52        Random rand = createRandom(); // use test framework's random seed
53        int s = rand.nextInt(0x7fff) % source.length();
54        int t = rand.nextInt(0x7fff) % source.length();
55        int slen = Math.abs(rand.nextInt(0x7fff) % source.length() - source.length()) % source.length();
56        int tlen = Math.abs(rand.nextInt(0x7fff) % source.length() - source.length()) % source.length();
57        String subs = source.substring(Math.min(s, slen), Math.min(s + slen, source.length()));
58        String subt = source.substring(Math.min(t, tlen), Math.min(t + tlen, source.length()));
59
60        CollationKey collationKey1, collationKey2;
61
62        myCollator.setStrength(Collator.TERTIARY);
63        collationKey1 = myCollator.getCollationKey(subs);
64        collationKey2 = myCollator.getCollationKey(subt);
65        int result = collationKey1.compareTo(collationKey2);  // Tertiary
66        int revResult = collationKey2.compareTo(collationKey1);  // Tertiary
67        report( subs, subt, result, revResult);
68
69        myCollator.setStrength(Collator.SECONDARY);
70        collationKey1 = myCollator.getCollationKey(subs);
71        collationKey2 = myCollator.getCollationKey(subt);
72        result = collationKey1.compareTo(collationKey2);  // Secondary
73        revResult = collationKey2.compareTo(collationKey1);   // Secondary
74        report( subs, subt, result, revResult);
75
76        myCollator.setStrength(Collator.PRIMARY);
77        collationKey1 = myCollator.getCollationKey(subs);
78        collationKey2 = myCollator.getCollationKey(subt);
79        result = collationKey1.compareTo(collationKey2);  // Primary
80        revResult = collationKey2.compareTo(collationKey1);   // Primary
81        report(subs, subt, result, revResult);
82
83        String msg = "";
84        String addOne = subs + String.valueOf(0xE000);
85
86        collationKey1 = myCollator.getCollationKey(subs);
87        collationKey2 = myCollator.getCollationKey(addOne);
88        result = collationKey1.compareTo(collationKey2);
89        if (result != -1) {
90            msg += "CollationKey(";
91            msg += subs;
92            msg += ") .LT. CollationKey(";
93            msg += addOne;
94            msg += ") Failed.";
95            errln(msg);
96        }
97
98        msg = "";
99        result = collationKey2.compareTo(collationKey1);
100        if (result != 1) {
101            msg += "CollationKey(";
102            msg += addOne;
103            msg += ") .GT. CollationKey(";
104            msg += subs;
105            msg += ") Failed.";
106            errln(msg);
107        }
108    }
109
110    // perform monkey tests using Collator.compare
111    @Test
112    public void TestCompare() {
113        if(source.length() == 0) {
114            errln("CollationMonkeyTest.TestCompare(): source is empty - ICU_DATA not set or data missing?");
115            return;
116        }
117
118        Collator myCollator;
119        try {
120             myCollator = Collator.getInstance(new Locale("en", "US"));
121        } catch (Exception e) {
122            warnln("ERROR: in creation of collator of ENGLISH locale");
123            return;
124        }
125
126        /* Seed the random-number generator with current time so that
127         * the numbers will be different every time we run.
128         */
129
130        Random rand = createRandom(); // use test framework's random seed
131        int s = rand.nextInt(0x7fff) % source.length();
132        int t = rand.nextInt(0x7fff) % source.length();
133        int slen = Math.abs(rand.nextInt(0x7fff) % source.length() - source.length()) % source.length();
134        int tlen = Math.abs(rand.nextInt(0x7fff) % source.length() - source.length()) % source.length();
135        String subs = source.substring(Math.min(s, slen), Math.min(s + slen, source.length()));
136        String subt = source.substring(Math.min(t, tlen), Math.min(t + tlen, source.length()));
137
138        myCollator.setStrength(Collator.TERTIARY);
139        int result = myCollator.compare(subs, subt);  // Tertiary
140        int revResult = myCollator.compare(subt, subs);  // Tertiary
141        report(subs, subt, result, revResult);
142
143        myCollator.setStrength(Collator.SECONDARY);
144        result = myCollator.compare(subs, subt);  // Secondary
145        revResult = myCollator.compare(subt, subs);  // Secondary
146        report(subs, subt, result, revResult);
147
148        myCollator.setStrength(Collator.PRIMARY);
149        result = myCollator.compare(subs, subt);  // Primary
150        revResult = myCollator.compare(subt, subs);  // Primary
151        report(subs, subt, result, revResult);
152
153        String msg = "";
154        String addOne = subs + String.valueOf(0xE000);
155
156        result = myCollator.compare(subs, addOne);
157        if (result != -1) {
158            msg += "Test : ";
159            msg += subs;
160            msg += " .LT. ";
161            msg += addOne;
162            msg += " Failed.";
163            errln(msg);
164        }
165
166        msg = "";
167        result = myCollator.compare(addOne, subs);
168        if (result != 1) {
169            msg += "Test : ";
170            msg += addOne;
171            msg += " .GT. ";
172            msg += subs;
173            msg += " Failed.";
174            errln(msg);
175        }
176    }
177
178    void report(String s, String t, int result, int revResult) {
179        if (revResult != -result) {
180            String msg = "";
181            msg += s;
182            msg += " and ";
183            msg += t;
184            msg += " round trip comparison failed";
185            msg += " (result " + result + ", reverse Result " + revResult + ")";
186            errln(msg);
187        }
188    }
189
190    @Test
191    public void TestRules() {
192        String testSourceCases[] = {
193            "\u0061\u0062\u007a",
194            "\u0061\u0062\u007a",
195        };
196
197        String testTargetCases[] = {
198            "\u0061\u0062\u00e4",
199            "\u0061\u0062\u0061\u0308",
200        };
201
202        int i=0;
203        logln("Demo Test 1 : Create a new table collation with rules \"& z < 0x00e4\"");
204        Collator col = Collator.getInstance(new Locale("en", "US"));
205        String baseRules = ((RuleBasedCollator)col).getRules();
206        String newRules = " & z < ";
207        newRules = baseRules + newRules + String.valueOf(0x00e4);
208        RuleBasedCollator myCollation = null;
209        try {
210            myCollation = new RuleBasedCollator(newRules);
211        } catch (Exception e) {
212            warnln( "Demo Test 1 Table Collation object creation failed.");
213            return;
214        }
215
216        for(i=0; i<2; i++){
217            doTest(myCollation, testSourceCases[i], testTargetCases[i], -1);
218        }
219        logln("Demo Test 2 : Create a new table collation with rules \"& z < a 0x0308\"");
220        newRules = "";
221        newRules = baseRules + " & z < a" + String.valueOf(0x0308);
222        try {
223            myCollation = new RuleBasedCollator(newRules);
224        } catch (Exception e) {
225            errln( "Demo Test 1 Table Collation object creation failed.");
226            return;
227        }
228        for(i=0; i<2; i++){
229            doTest(myCollation, testSourceCases[i], testTargetCases[i], -1);
230        }
231    }
232
233    void doTest(RuleBasedCollator myCollation, String mysource, String target, int result) {
234        int compareResult = myCollation.compare(source, target);
235        CollationKey sortKey1, sortKey2;
236
237        try {
238            sortKey1 = myCollation.getCollationKey(source);
239            sortKey2 = myCollation.getCollationKey(target);
240        } catch (Exception e) {
241            errln("SortKey generation Failed.\n");
242            return;
243        }
244        int keyResult = sortKey1.compareTo(sortKey2);
245        reportCResult( mysource, target, sortKey1, sortKey2, compareResult, keyResult, compareResult, result );
246    }
247
248    public void reportCResult(String src, String target, CollationKey sourceKey, CollationKey targetKey,
249                              int compareResult, int keyResult, int incResult, int expectedResult ) {
250        if (expectedResult < -1 || expectedResult > 1) {
251            errln("***** invalid call to reportCResult ****");
252            return;
253        }
254        boolean ok1 = (compareResult == expectedResult);
255        boolean ok2 = (keyResult == expectedResult);
256        boolean ok3 = (incResult == expectedResult);
257        if (ok1 && ok2 && ok3 && !isVerbose()) {
258            return;
259        } else {
260            String msg1 = ok1? "Ok: compare(\"" : "FAIL: compare(\"";
261            String msg2 = "\", \"";
262            String msg3 = "\") returned ";
263            String msg4 = "; expected ";
264            String sExpect = new String("");
265            String sResult = new String("");
266            sResult = CollationTest.appendCompareResult(compareResult, sResult);
267            sExpect = CollationTest.appendCompareResult(expectedResult, sExpect);
268            if (ok1) {
269                logln(msg1 + src + msg2 + target + msg3 + sResult);
270            } else {
271                errln(msg1 + src + msg2 + target + msg3 + sResult + msg4 + sExpect);
272            }
273            msg1 = ok2 ? "Ok: key(\"" : "FAIL: key(\"";
274            msg2 = "\").compareTo(key(\"";
275            msg3 = "\")) returned ";
276            sResult = CollationTest.appendCompareResult(keyResult, sResult);
277            if (ok2) {
278                logln(msg1 + src + msg2 + target + msg3 + sResult);
279            } else {
280                errln(msg1 + src + msg2 + target + msg3 + sResult + msg4 + sExpect);
281                msg1 = "  ";
282                msg2 = " vs. ";
283                errln(msg1 + CollationTest.prettify(sourceKey) + msg2 + CollationTest.prettify(targetKey));
284            }
285            msg1 = ok3 ? "Ok: incCompare(\"" : "FAIL: incCompare(\"";
286            msg2 = "\", \"";
287            msg3 = "\") returned ";
288            sResult = CollationTest.appendCompareResult(incResult, sResult);
289            if (ok3) {
290                logln(msg1 + src + msg2 + target + msg3 + sResult);
291            } else {
292                errln(msg1 + src + msg2 + target + msg3 + sResult + msg4 + sExpect);
293            }
294        }
295    }
296}
297