1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7#include "unicode/utypes.h"
8
9#if !UCONFIG_NO_COLLATION
10
11#include "unicode/coll.h"
12#include "unicode/tblcoll.h"
13#include "unicode/unistr.h"
14#include "unicode/sortkey.h"
15#include "g7coll.h"
16#include "sfwdchit.h"
17
18#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
19
20static const UChar testCases[][G7CollationTest::MAX_TOKEN_LEN] = {
21    {  0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
22        0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073 /*'s'*/, 0x0000},                    /* 9 */
23    { 0x0050 /*'P'*/, 0x0061 /*'a'*/, 0x0074/*'t'*/, 0x0000},                                                    /* 1 */
24    { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x00E9, 0x0000},                                    /* 2 */
25    { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0000},                           /* 3 */
26    { 0x0070 /*'p'*/, 0x00E9, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000},            /* 4 */
27    { 0x0070 /*'p'*/, 0x00EA, 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0065 /*'e'*/, 0x0072 /*'r'*/, 0x0000},            /* 5 */
28    { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0064 /*'d'*/, 0x0000},                                                    /* 6 */
29    { 0x0054 /*'T'*/, 0x00F6, 0x006e /*'n'*/, 0x0065 /*'e'*/, 0x0000},                                            /* 7 */
30    { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x0066 /*'f'*/, 0x0075 /*'u'*/, 0x0000},                                   /* 8 */
31    { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
32      0x0062  /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000},                                    /* 12 */
33    { 0x0054 /*'T'*/, 0x006f /*'o'*/, 0x006e /*'n'*/, 0x0000},                                                    /* 10 */
34    { 0x0050  /*'P'*/, 0x0041 /*'A'*/, 0x0054 /*'T'*/, 0x0000},                                                    /* 11 */
35    { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
36        0x002d /*'-'*/,  0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0000},                /* 13 */
37    { 0x0062 /*'b'*/, 0x006c /*'l'*/, 0x0061 /*'a'*/, 0x0062 /*'c'*/, 0x006b /*'k'*/,
38        0x002d /*'-'*/,  0x0062 /*'b'*/, 0x0069 /*'i'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0073/*'s'*/, 0x0000},  /* 0 */
39    {0x0070 /*'p'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x0000},                                                    /* 14 */
40    /* Additional tests */
41    { 0x0063 /*'c'*/, 0x007a /*'z'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0000 },                                 /* 15 */
42    { 0x0063 /*'c'*/, 0x0068 /*'h'*/, 0x0075 /*'u'*/, 0x0072 /*'r'*/, 0x006f /*'o'*/, 0x0000 },                  /* 16 */
43    { 0x0063 /*'c'*/, 0x0061 /*'a'*/, 0x0074 /*'t'*/, 0x000 },                                                    /* 17 */
44    { 0x0064 /*'d'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x006e /*'n'*/, 0x0000 },                                 /* 18 */
45    { 0x003f /*'?'*/, 0x0000 },                                                                                /* 19 */
46    { 0x0071 /*'q'*/, 0x0075 /*'u'*/, 0x0069 /*'i'*/, 0x0063 /*'c'*/, 0x006b /*'k'*/, 0x0000 },                  /* 20 */
47    { 0x0023 /*'#'*/, 0x0000 },                                                                                /* 21 */
48    { 0x0026 /*'&'*/, 0x0000 },                                                                                /* 22 */
49    {  0x0061 /*'a'*/, 0x002d /*'-'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/,
50                0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000},                                                        /* 24 */
51    { 0x0061 /*'a'*/, 0x0061 /*'a'*/, 0x0072 /*'r'*/, 0x0064 /*'d'*/, 0x0076 /*'v'*/, 0x0061 /*'a'*/,
52                0x0072/*'r'*/, 0x006b/*'k'*/, 0x0000},                                                        /* 23 */
53    { 0x0061 /*'a'*/, 0x0062 /*'b'*/, 0x0062 /*'b'*/, 0x006f /*'o'*/, 0x0074 /*'t'*/, 0x0000},                   /* 25 */
54    { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x002d /*'-'*/, 0x0070 /*'p'*/, 0x0000},                                 /* 27 */
55    { 0x0063 /*'c'*/, 0x006f  /*'o'*/, 0x0070 /*'p'*/, 0x0000},                                                /* 28 */
56    { 0x0063 /*'c'*/, 0x006f /*'o'*/, 0x006f /*'o'*/, 0x0070 /*'p'*/, 0x0000},                                 /* 26 */
57    { 0x007a /*'z'*/, 0x0065  /*'e'*/, 0x0062 /*'b'*/, 0x0072 /*'r'*/, 0x0061 /*'a'*/, 0x0000}                    /* 29 */
58};
59
60static const int32_t results[G7CollationTest::TESTLOCALES][G7CollationTest::TOTALTESTSET] = {
61    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_US */
62    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_GB */
63    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* en_CA */
64    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_FR */
65    { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* fr_CA */
66    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* de_DE */
67    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* it_IT */
68    { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4, 5, 6, 8, 10, 7, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, /* ja_JP */
69    /* new table collation with rules "& Z < p, P"  loop to FIXEDTESTSET */
70    { 12, 13, 9, 0, 6, 8, 10, 7, 14, 1, 11, 2, 3, 4, 5, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 },
71    /* new table collation with rules "& C < ch , cH, Ch, CH " loop to TOTALTESTSET */
72    { 19, 22, 21, 23, 24, 25, 12, 13, 9, 0, 17, 26, 28, 27, 15, 16, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 },
73    /* new table collation with rules "& Question-mark ; ? & Hash-mark ; # & Ampersand ; '&'  " loop to TOTALTESTSET */
74    { 23, 24, 25, 22, 12, 13, 9, 0, 17, 16, 26, 28, 27, 15, 18, 21, 14, 1, 11, 2, 3, 4, 5, 19, 20, 6, 8, 10, 7, 29 },
75    /* analogous to Japanese rules " & aa ; a- & ee ; e- & ii ; i- & oo ; o- & uu ; u- " */  /* loop to TOTALTESTSET */
76    { 19, 22, 21, 24, 23, 25, 12, 13, 9, 0, 17, 16, 28, 26, 27, 15, 18, 14, 1, 11, 2, 3, 4, 5, 20, 6, 8, 10, 7, 29 }
77};
78
79G7CollationTest::~G7CollationTest() {}
80
81void G7CollationTest::TestG7Locales(/* char* par */)
82{
83    int32_t i;
84    const Locale locales[8] = {
85        Locale("en", "US", ""),
86        Locale("en", "GB", ""),
87        Locale("en", "CA", ""),
88        Locale("fr", "FR", ""),
89        Locale("fr", "CA", ""),
90        Locale("de", "DE", ""),
91        Locale("it", "IT", ""),
92        Locale("ja", "JP", "")
93    };
94
95    for (i = 0; i < LENGTHOF(locales); i++)
96    {
97        UnicodeString dispName;
98        UErrorCode status = U_ZERO_ERROR;
99
100        const Locale &locale = locales[i];
101        LocalPointer<Collator> myCollation(Collator::createInstance(locale, status));
102        if(U_FAILURE(status)) {
103          errcheckln(status, "Couldn't instantiate collator. Error: %s", u_errorName(status));
104          return;
105        }
106        myCollation->setStrength(Collator::QUATERNARY);
107        myCollation->setAttribute(UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, status);
108        if (U_FAILURE(status)) {
109            errln("Locale %s creation failed - %s", locale.getName(), u_errorName(status));
110            continue;
111        }
112
113        const UnicodeString &rules = ((RuleBasedCollator*)myCollation.getAlias())->getRules();
114        if (rules.isEmpty() &&
115                (locale == Locale::getCanadaFrench() || locale == Locale::getJapanese())) {
116            dataerrln("%s Collator missing rule string", locale.getName());
117            if (logKnownIssue("10671", "TestG7Locales does not test ignore-punctuation")) {
118                continue;
119            }
120        } else {
121            status = U_ZERO_ERROR;
122            RuleBasedCollator *tblColl1 = new RuleBasedCollator(rules, status);
123            if (U_FAILURE(status)) {
124                errln("Recreate %s collation failed - %s", locale.getName(), u_errorName(status));
125                continue;
126            }
127            myCollation.adoptInstead(tblColl1);
128        }
129
130        UnicodeString msg;
131
132        msg += "Locale ";
133        msg += locales[i].getDisplayName(dispName);
134        msg += "tests start :";
135        logln(msg);
136
137        int32_t j, n;
138        for (j = 0; j < FIXEDTESTSET; j++)
139        {
140            for (n = j+1; n < FIXEDTESTSET; n++)
141            {
142                doTest(myCollation.getAlias(), testCases[results[i][j]], testCases[results[i][n]], Collator::LESS);
143            }
144        }
145    }
146}
147
148void G7CollationTest::TestDemo1(/* char* par */)
149{
150    logln("Demo Test 1 : Create a new table collation with rules \"& Z < p, P\"");
151    UErrorCode status = U_ZERO_ERROR;
152    Collator *col = Collator::createInstance("en_US", status);
153    if(U_FAILURE(status)) {
154      delete col;
155      errcheckln(status, "Couldn't instantiate collator. Error: %s", u_errorName(status));
156      return;
157    }
158    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
159    UnicodeString newRules(" & Z < p, P");
160    newRules.insert(0, baseRules);
161    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);
162
163    if (U_FAILURE(status))
164    {
165        errln( "Demo Test 1 Table Collation object creation failed.");
166        return;
167    }
168
169    int32_t j, n;
170    for (j = 0; j < FIXEDTESTSET; j++)
171    {
172        for (n = j+1; n < FIXEDTESTSET; n++)
173        {
174            doTest(myCollation, testCases[results[8][j]], testCases[results[8][n]], Collator::LESS);
175        }
176    }
177
178    delete myCollation;
179    delete col;
180}
181
182void G7CollationTest::TestDemo2(/* char* par */)
183{
184    logln("Demo Test 2 : Create a new table collation with rules \"& C < ch , cH, Ch, CH\"");
185    UErrorCode status = U_ZERO_ERROR;
186    Collator *col = Collator::createInstance("en_US", status);
187    if(U_FAILURE(status)) {
188      delete col;
189      errcheckln(status, "Couldn't instantiate collator. Error: %s", u_errorName(status));
190      return;
191    }
192    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
193    UnicodeString newRules("& C < ch , cH, Ch, CH");
194    newRules.insert(0, baseRules);
195    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);
196
197    if (U_FAILURE(status))
198    {
199        errln("Demo Test 2 Table Collation object creation failed.");
200        return;
201    }
202
203    int32_t j, n;
204    for (j = 0; j < TOTALTESTSET; j++)
205    {
206        for (n = j+1; n < TOTALTESTSET; n++)
207        {
208            doTest(myCollation, testCases[results[9][j]], testCases[results[9][n]], Collator::LESS);
209        }
210    }
211
212    delete myCollation;
213    delete col;
214}
215
216void G7CollationTest::TestDemo3(/* char* par */)
217{
218    logln("Demo Test 3 : Create a new table collation with rules \"& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'\"");
219    UErrorCode status = U_ZERO_ERROR;
220    Collator *col = Collator::createInstance("en_US", status);
221    if(U_FAILURE(status)) {
222      errcheckln(status, "Couldn't instantiate collator. Error: %s", u_errorName(status));
223      delete col;
224      return;
225    }
226    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
227    UnicodeString newRules = "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'";
228    newRules.insert(0, baseRules);
229    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);
230
231    if (U_FAILURE(status))
232    {
233        errln("Demo Test 3 Table Collation object creation failed.");
234        return;
235    }
236
237    int32_t j, n;
238    for (j = 0; j < TOTALTESTSET; j++)
239    {
240        for (n = j+1; n < TOTALTESTSET; n++)
241        {
242            doTest(myCollation, testCases[results[10][j]], testCases[results[10][n]], Collator::LESS);
243        }
244    }
245
246    delete myCollation;
247    delete col;
248}
249
250void G7CollationTest::TestDemo4(/* char* par */)
251{
252    logln("Demo Test 4 : Create a new table collation with rules \" & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' \"");
253    UErrorCode status = U_ZERO_ERROR;
254    Collator *col = Collator::createInstance("en_US", status);
255    if(U_FAILURE(status)) {
256      delete col;
257      errcheckln(status, "Couldn't instantiate collator. Error: %s", u_errorName(status));
258      return;
259    }
260
261    const UnicodeString baseRules = ((RuleBasedCollator*)col)->getRules();
262    UnicodeString newRules = " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' ";
263    newRules.insert(0, baseRules);
264    RuleBasedCollator *myCollation = new RuleBasedCollator(newRules, status);
265
266    int32_t j, n;
267    for (j = 0; j < TOTALTESTSET; j++)
268    {
269        for (n = j+1; n < TOTALTESTSET; n++)
270        {
271            doTest(myCollation, testCases[results[11][j]], testCases[results[11][n]], Collator::LESS);
272        }
273    }
274
275    delete myCollation;
276    delete col;
277}
278
279void G7CollationTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
280{
281    if (exec) logln("TestSuite G7CollationTest: ");
282    switch (index) {
283        case 0: name = "TestG7Locales"; if (exec)   TestG7Locales(/* par */); break;
284        case 1: name = "TestDemo1"; if (exec)   TestDemo1(/* par */); break;
285        case 2: name = "TestDemo2"; if (exec)   TestDemo2(/* par */); break;
286        case 3: name = "TestDemo3"; if (exec)   TestDemo3(/* par */); break;
287        case 4: name = "TestDemo4"; if (exec)   TestDemo4(/* par */); break;
288        default: name = ""; break;
289    }
290}
291
292#endif /* #if !UCONFIG_NO_COLLATION */
293