1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/********************************************************************
5 * Copyright (c) 2002-2014, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9/**
10 * UCAConformanceTest performs conformance tests defined in the data
11 * files. ICU ships with stub data files, as the whole test are too
12 * long. To do the whole test, download the test files.
13 */
14
15package android.icu.dev.test.collator;
16
17import java.io.BufferedReader;
18import java.io.IOException;
19
20import org.junit.Before;
21import org.junit.Test;
22import org.junit.runner.RunWith;
23import org.junit.runners.JUnit4;
24
25import android.icu.dev.test.TestFmwk;
26import android.icu.dev.test.TestUtil;
27import android.icu.lang.UCharacter;
28import android.icu.text.Collator;
29import android.icu.text.RawCollationKey;
30import android.icu.text.RuleBasedCollator;
31import android.icu.text.UTF16;
32import android.icu.util.ULocale;
33import android.icu.util.VersionInfo;
34import android.icu.testsharding.MainTestShard;
35
36@MainTestShard
37@RunWith(JUnit4.class)
38public class UCAConformanceTest extends TestFmwk {
39
40    public UCAConformanceTest() {
41    }
42
43    @Before
44    public void init() throws Exception {
45        UCA = (RuleBasedCollator) Collator.getInstance(ULocale.ROOT);
46        comparer = new UTF16.StringComparator(true, false, UTF16.StringComparator.FOLD_CASE_DEFAULT);
47    }
48
49    private RuleBasedCollator UCA;
50    private RuleBasedCollator rbUCA;
51    private UTF16.StringComparator comparer;
52    private boolean isAtLeastUCA62 = UCharacter.getUnicodeVersion().compareTo(VersionInfo.UNICODE_6_2) >= 0;
53
54    @Test
55    public void TestTableNonIgnorable() {
56        setCollNonIgnorable(UCA);
57        openTestFile("NON_IGNORABLE");
58        conformanceTest(UCA);
59    }
60
61    @Test
62    public void TestTableShifted() {
63        setCollShifted(UCA);
64        openTestFile("SHIFTED");
65        conformanceTest(UCA);
66    }
67
68    @Test
69    public void TestRulesNonIgnorable() {
70        if (logKnownIssue("cldrbug:6745", "UCARules.txt has problems")) {
71            return;
72        }
73        initRbUCA();
74        if (rbUCA == null) {
75            return;
76        }
77
78        setCollNonIgnorable(rbUCA);
79        openTestFile("NON_IGNORABLE");
80        conformanceTest(rbUCA);
81    }
82
83    @Test
84    public void TestRulesShifted() {
85        logln("This test is currently disabled, as it is impossible to "
86                + "wholly represent fractional UCA using tailoring rules.");
87        return;
88        /*
89         * initRbUCA(); if(rbUCA == null) { return; }
90         *
91         * setCollShifted(rbUCA); openTestFile("SHIFTED"); testConformance(rbUCA);
92         */
93    }
94
95    BufferedReader in;
96
97    private void openTestFile(String type) {
98        String collationTest = "CollationTest_";
99        String ext = ".txt";
100        try {
101            in = TestUtil.getDataReader(collationTest + type + "_SHORT" + ext);
102        } catch (Exception e) {
103            try {
104                in = TestUtil.getDataReader(collationTest + type + ext);
105            } catch (Exception e1) {
106                try {
107                    in = TestUtil.getDataReader(collationTest + type + "_STUB" + ext);
108                    logln("INFO: Working with the stub file.\n" + "If you need the full conformance test, please\n"
109                            + "download the appropriate data files from:\n"
110                            + "http://unicode.org/cldr/trac/browser/trunk/common/uca");
111                } catch (Exception e11) {
112                    errln("ERROR: Could not find any of the test files");
113                }
114            }
115        }
116    }
117
118    private void setCollNonIgnorable(RuleBasedCollator coll) {
119        if (coll != null) {
120            coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
121            coll.setLowerCaseFirst(false);
122            coll.setCaseLevel(false);
123            coll.setStrength(isAtLeastUCA62 ? Collator.IDENTICAL : Collator.TERTIARY);
124            coll.setAlternateHandlingShifted(false);
125        }
126    }
127
128    private void setCollShifted(RuleBasedCollator coll) {
129        if (coll != null) {
130            coll.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
131            coll.setLowerCaseFirst(false);
132            coll.setCaseLevel(false);
133            coll.setStrength(isAtLeastUCA62 ? Collator.IDENTICAL : Collator.QUATERNARY);
134            coll.setAlternateHandlingShifted(true);
135        }
136    }
137
138    private void initRbUCA() {
139        if (rbUCA == null) {
140            String ucarules = UCA.getRules(true);
141            try {
142                rbUCA = new RuleBasedCollator(ucarules);
143            } catch (Exception e) {
144                errln("Failure creating UCA rule-based collator: " + e);
145            }
146        }
147    }
148
149    private String parseString(String line) {
150        int i = 0, value;
151        StringBuilder result = new StringBuilder(), buffer = new StringBuilder();
152
153        for (;;) {
154            while (i < line.length() && Character.isWhitespace(line.charAt(i))) {
155                i++;
156            }
157            while (i < line.length() && Character.isLetterOrDigit(line.charAt(i))) {
158                buffer.append(line.charAt(i));
159                i++;
160            }
161            if (buffer.length() == 0) {
162                // We hit something that was not whitespace/letter/digit.
163                // Should be ';' or end of string.
164                return result.toString();
165            }
166            /* read one code point */
167            value = Integer.parseInt(buffer.toString(), 16);
168            buffer.setLength(0);
169            result.appendCodePoint(value);
170        }
171
172    }
173
174    private static final int IS_SHIFTED = 1;
175    private static final int FROM_RULES = 2;
176
177    private static boolean skipLineBecauseOfBug(String s, int flags) {
178        // Add temporary exceptions here if there are ICU bugs, until we can fix them.
179        // For examples see the ICU 52 version of this file.
180        return false;
181    }
182
183    private static int normalizeResult(int result) {
184        return result < 0 ? -1 : result == 0 ? 0 : 1;
185    }
186
187    private void conformanceTest(RuleBasedCollator coll) {
188        if (in == null || coll == null) {
189            return;
190        }
191        int skipFlags = 0;
192        if (coll.isAlternateHandlingShifted()) {
193            skipFlags |= IS_SHIFTED;
194        }
195        if (coll == rbUCA) {
196            skipFlags |= FROM_RULES;
197        }
198
199        logln("-prop:ucaconfnosortkeys=1 turns off getSortKey() in UCAConformanceTest");
200        boolean withSortKeys = getProperty("ucaconfnosortkeys") == null;
201
202        int lineNo = 0;
203
204        String line = null, oldLine = null, buffer = null, oldB = null;
205        RawCollationKey sk1 = new RawCollationKey(), sk2 = new RawCollationKey();
206        RawCollationKey oldSk = null, newSk = sk1;
207
208        try {
209            while ((line = in.readLine()) != null) {
210                lineNo++;
211                if (line.length() == 0 || line.charAt(0) == '#') {
212                    continue;
213                }
214                buffer = parseString(line);
215
216                if (skipLineBecauseOfBug(buffer, skipFlags)) {
217                    logln("Skipping line " + lineNo + " because of a known bug");
218                    continue;
219                }
220
221                if (withSortKeys) {
222                    coll.getRawCollationKey(buffer, newSk);
223                }
224                if (oldSk != null) {
225                    boolean ok = true;
226                    int skres = withSortKeys ? oldSk.compareTo(newSk) : 0;
227                    int cmpres = coll.compare(oldB, buffer);
228                    int cmpres2 = coll.compare(buffer, oldB);
229
230                    if (cmpres != -cmpres2) {
231                        errln(String.format(
232                                "Compare result not symmetrical on line %d: "
233                                        + "previous vs. current (%d) / current vs. previous (%d)",
234                                lineNo, cmpres, cmpres2));
235                        ok = false;
236                    }
237
238                    // TODO: Compare with normalization turned off if the input passes the FCD test.
239
240                    if (withSortKeys && cmpres != normalizeResult(skres)) {
241                        errln("Difference between coll.compare (" + cmpres + ") and sortkey compare (" + skres
242                                + ") on line " + lineNo);
243                        ok = false;
244                    }
245
246                    int res = cmpres;
247                    if (res == 0 && !isAtLeastUCA62) {
248                        // Up to UCA 6.1, the collation test files use a custom tie-breaker,
249                        // comparing the raw input strings.
250                        res = comparer.compare(oldB, buffer);
251                        // Starting with UCA 6.2, the collation test files use the standard UCA tie-breaker,
252                        // comparing the NFD versions of the input strings,
253                        // which we do via setting strength=identical.
254                    }
255                    if (res > 0) {
256                        errln("Line " + lineNo + " is not greater or equal than previous line");
257                        ok = false;
258                    }
259
260                    if (!ok) {
261                        errln("  Previous data line " + oldLine);
262                        errln("  Current data line  " + line);
263                        if (withSortKeys) {
264                            errln("  Previous key: " + CollationTest.prettify(oldSk));
265                            errln("  Current key:  " + CollationTest.prettify(newSk));
266                        }
267                    }
268                }
269
270                oldSk = newSk;
271                oldB = buffer;
272                oldLine = line;
273                if (oldSk == sk1) {
274                    newSk = sk2;
275                } else {
276                    newSk = sk1;
277                }
278            }
279        } catch (Exception e) {
280            errln("Unexpected exception " + e);
281        } finally {
282            try {
283                in.close();
284            } catch (IOException ignored) {
285            }
286            in = null;
287        }
288    }
289}
290