~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/test/intltest/transtst.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
**********************************************************************
3
 
*   Copyright (C) 2001, International Business Machines
4
 
*   Corporation and others.  All Rights Reserved.
5
 
**********************************************************************
6
 
*   Date        Name        Description
7
 
*   11/10/99    aliu        Creation.
8
 
**********************************************************************
9
 
*/
10
 
#include "transtst.h"
11
 
#include "unicode/cpdtrans.h"
12
 
#include "unicode/dtfmtsym.h"
13
 
#include "unicode/hextouni.h"
14
 
#include "unicode/normlzr.h"
15
 
#include "unicode/nultrans.h"
16
 
#include "unicode/rbt.h"
17
 
#include "unicode/translit.h"
18
 
#include "unicode/ucnv.h"
19
 
#include "unicode/ucnv_err.h"
20
 
#include "unicode/uchar.h"
21
 
#include "unicode/unifilt.h"
22
 
#include "unicode/uniset.h"
23
 
#include "unicode/unitohex.h"
24
 
#include "unicode/utypes.h"
25
 
#include "unicode/ustring.h"
26
 
 
27
 
/***********************************************************************
28
 
 
29
 
                     HOW TO USE THIS TEST FILE
30
 
                               -or-
31
 
                  How I developed on two platforms
32
 
                without losing (too much of) my mind
33
 
 
34
 
 
35
 
1. Add new tests by copying/pasting/changing existing tests.  On Java,
36
 
   any public void method named Test...() taking no parameters becomes
37
 
   a test.  On C++, you need to modify the header and add a line to
38
 
   the runIndexedTest() dispatch method.
39
 
 
40
 
2. Make liberal use of the expect() method; it is your friend.
41
 
 
42
 
3. The tests in this file exactly match those in a sister file on the
43
 
   other side.  The two files are:
44
 
 
45
 
   icu4j:  src/com/ibm/test/translit/TransliteratorTest.java
46
 
   icu4c:  source/test/intltest/transtst.cpp
47
 
 
48
 
                  ==> THIS IS THE IMPORTANT PART <==
49
 
 
50
 
   When you add a test in this file, add it in TransliteratorTest.java
51
 
   too.  Give it the same name and put it in the same relative place.
52
 
   This makes maintenance a lot simpler for any poor soul who ends up
53
 
   trying to synchronize the tests between icu4j and icu4c.
54
 
 
55
 
4. If you MUST enter a test that is NOT paralleled in the sister file,
56
 
   then add it in the special non-mirrored section.  These are
57
 
   labeled
58
 
 
59
 
     "icu4j ONLY"
60
 
 
61
 
   or
62
 
 
63
 
     "icu4c ONLY"
64
 
 
65
 
   Make sure you document the reason the test is here and not there.
66
 
 
67
 
 
68
 
Thank you.
69
 
The Management
70
 
***********************************************************************/
71
 
 
72
 
// Define character constants thusly to be EBCDIC-friendly
73
 
enum {
74
 
    LEFT_BRACE=((UChar)0x007B), /*{*/
75
 
    PIPE      =((UChar)0x007C), /*|*/
76
 
    ZERO      =((UChar)0x0030), /*0*/
77
 
    UPPER_A   =((UChar)0x0041)  /*A*/
78
 
};
79
 
 
80
 
TransliteratorTest::TransliteratorTest()
81
 
:   DESERET_DEE((UChar32)0x10414),
82
 
    DESERET_dee((UChar32)0x1043C)
83
 
{
84
 
}
85
 
 
86
 
void
87
 
TransliteratorTest::runIndexedTest(int32_t index, UBool exec,
88
 
                                   const char* &name, char* /*par*/) {
89
 
    switch (index) {
90
 
        TESTCASE(0,TestInstantiation);
91
 
        TESTCASE(1,TestSimpleRules);
92
 
        TESTCASE(2,TestRuleBasedInverse);
93
 
        TESTCASE(3,TestKeyboard);
94
 
        TESTCASE(4,TestKeyboard2);
95
 
        TESTCASE(5,TestKeyboard3);
96
 
        TESTCASE(6,TestArabic);
97
 
        TESTCASE(7,TestCompoundKana);
98
 
        TESTCASE(8,TestCompoundHex);
99
 
        TESTCASE(9,TestFiltering);
100
 
        TESTCASE(10,TestInlineSet);
101
 
        TESTCASE(11,TestPatternQuoting);
102
 
        TESTCASE(12,TestJ277);
103
 
        TESTCASE(13,TestJ243);
104
 
        TESTCASE(14,TestJ329);
105
 
        TESTCASE(15,TestSegments);
106
 
        TESTCASE(16,TestCursorOffset);
107
 
        TESTCASE(17,TestArbitraryVariableValues);
108
 
        TESTCASE(18,TestPositionHandling);
109
 
        TESTCASE(19,TestHiraganaKatakana);
110
 
        TESTCASE(20,TestCopyJ476);
111
 
        TESTCASE(21,TestAnchors);
112
 
        TESTCASE(22,TestInterIndic);
113
 
        TESTCASE(23,TestFilterIDs);
114
 
        TESTCASE(24,TestCaseMap);
115
 
        TESTCASE(25,TestNameMap);
116
 
        TESTCASE(26,TestLiberalizedID);
117
 
        TESTCASE(27,TestCreateInstance);
118
 
        TESTCASE(28,TestNormalizationTransliterator);
119
 
        TESTCASE(29,TestCompoundRBT);
120
 
        TESTCASE(30,TestCompoundFilter);
121
 
        TESTCASE(31,TestRemove);
122
 
        TESTCASE(32,TestToRules);
123
 
        TESTCASE(33,TestContext);
124
 
        TESTCASE(34,TestSupplemental);
125
 
        TESTCASE(35,TestQuantifier);
126
 
        TESTCASE(36,TestSTV);
127
 
        TESTCASE(37,TestCompoundInverse);
128
 
        TESTCASE(38,TestNFDChainRBT);
129
 
        TESTCASE(39,TestNullInverse);
130
 
        TESTCASE(40,TestAliasInverseID);
131
 
        TESTCASE(41,TestCompoundInverseID);
132
 
        TESTCASE(42,TestUndefinedVariable);
133
 
        TESTCASE(43,TestEmptyContext);
134
 
        TESTCASE(44,TestCompoundFilterID);
135
 
        TESTCASE(45,TestPropertySet);
136
 
        TESTCASE(46,TestNewEngine);
137
 
        TESTCASE(47,TestQuantifiedSegment);
138
 
        TESTCASE(48,TestDevanagariLatinRT);
139
 
        TESTCASE(49,TestTeluguLatinRT);
140
 
        TESTCASE(50,TestCompoundLatinRT);
141
 
        TESTCASE(51,TestSanskritLatinRT);
142
 
        TESTCASE(52,TestLocaleInstantiation);
143
 
        TESTCASE(53,TestTitleAccents);
144
 
        TESTCASE(54,TestLocaleResource);
145
 
        TESTCASE(55,TestParseError);
146
 
        TESTCASE(56,TestOutputSet);
147
 
        TESTCASE(57,TestVariableRange);
148
 
        TESTCASE(58,TestInvalidPostContext);
149
 
        TESTCASE(59,TestIDForms);
150
 
        TESTCASE(60,TestToRulesMark);
151
 
        TESTCASE(61,TestEscape);
152
 
        TESTCASE(62,TestAnchorMasking);
153
 
        TESTCASE(63,TestDisplayName);
154
 
        TESTCASE(64,TestSpecialCases);
155
 
        TESTCASE(65,TestIncrementalProgress);
156
 
        TESTCASE(66,TestSurrogateCasing);
157
 
        TESTCASE(67,TestFunction);
158
 
        TESTCASE(68,TestInvalidBackRef);
159
 
 
160
 
        default: name = ""; break;
161
 
    }
162
 
}
163
 
 
164
 
/**
165
 
 * Make sure every system transliterator can be instantiated.
166
 
 * 
167
 
 * ALSO test that the result of toRules() for each rule is a valid
168
 
 * rule.  Do this here so we don't have to have another test that
169
 
 * instantiates everything as well.
170
 
 */
171
 
void TransliteratorTest::TestInstantiation() {
172
 
    int32_t n = Transliterator::countAvailableIDs();
173
 
    UnicodeString name;
174
 
    for (int32_t i=0; i<n; ++i) {
175
 
        UnicodeString id = Transliterator::getAvailableID(i);
176
 
        if (id.length() < 1) {
177
 
            errln(UnicodeString("FAIL: getAvailableID(") +
178
 
                  i + ") returned empty string");
179
 
            continue;
180
 
        }
181
 
        UParseError parseError;
182
 
        UErrorCode status = U_ZERO_ERROR;
183
 
        Transliterator* t = Transliterator::createInstance(id,
184
 
                              UTRANS_FORWARD, parseError,status);
185
 
        name.truncate(0);
186
 
        Transliterator::getDisplayName(id, name);
187
 
        if (t == 0) {
188
 
            errln(UnicodeString("FAIL: Couldn't create ") + id +
189
 
                  /*", parse error " + parseError.code +*/
190
 
                  ", line " + parseError.line +
191
 
                  ", offset " + parseError.offset +
192
 
                  ", pre-context " + prettify(parseError.preContext, TRUE) +
193
 
                  ", post-context " +prettify(parseError.postContext,TRUE) +
194
 
                  ", Error: " + u_errorName(status));
195
 
            // When createInstance fails, it deletes the failing
196
 
            // entry from the available ID list.  We detect this
197
 
            // here by looking for a change in countAvailableIDs.
198
 
            int32_t nn = Transliterator::countAvailableIDs();
199
 
            if (nn == (n - 1)) {
200
 
                n = nn;
201
 
                --i; // Compensate for deleted entry
202
 
            }
203
 
        } else {
204
 
            logln(UnicodeString("OK: ") + name + " (" + id + ")");
205
 
 
206
 
            // Now test toRules
207
 
            UnicodeString rules;
208
 
            t->toRules(rules, TRUE);
209
 
            Transliterator *u = Transliterator::createFromRules("x",
210
 
                                    rules, UTRANS_FORWARD, parseError,status);
211
 
            if (u == 0) {
212
 
                errln(UnicodeString("FAIL: ") + id +
213
 
                      ".createFromRules() => bad rules" +
214
 
                      /*", parse error " + parseError.code +*/
215
 
                      ", line " + parseError.line +
216
 
                      ", offset " + parseError.offset +
217
 
                      ", context " + prettify(parseError.preContext, TRUE) +
218
 
                      ", rules: " + prettify(rules, TRUE));
219
 
            } else {
220
 
                delete u;
221
 
            }
222
 
            delete t;
223
 
        }
224
 
    }
225
 
 
226
 
    // Now test the failure path
227
 
    UParseError parseError;
228
 
    UErrorCode status = U_ZERO_ERROR;
229
 
    UnicodeString id("<Not a valid Transliterator ID>");
230
 
    Transliterator* t = Transliterator::createInstance(id, UTRANS_FORWARD, parseError, status);
231
 
    if (t != 0) {
232
 
        errln("FAIL: " + id + " returned a transliterator");
233
 
        delete t;
234
 
    } else {
235
 
        logln("OK: Bogus ID handled properly");
236
 
    }
237
 
}
238
 
 
239
 
void TransliteratorTest::TestSimpleRules(void) {
240
 
    /* Example: rules 1. ab>x|y
241
 
     *                2. yc>z
242
 
     *
243
 
     * []|eabcd  start - no match, copy e to tranlated buffer
244
 
     * [e]|abcd  match rule 1 - copy output & adjust cursor
245
 
     * [ex|y]cd  match rule 2 - copy output & adjust cursor
246
 
     * [exz]|d   no match, copy d to transliterated buffer
247
 
     * [exzd]|   done
248
 
     */
249
 
    expect(UnicodeString("ab>x|y;", "") +
250
 
           "yc>z",
251
 
           "eabcd", "exzd");
252
 
 
253
 
    /* Another set of rules:
254
 
     *    1. ab>x|yzacw
255
 
     *    2. za>q
256
 
     *    3. qc>r
257
 
     *    4. cw>n
258
 
     *
259
 
     * []|ab       Rule 1
260
 
     * [x|yzacw]   No match
261
 
     * [xy|zacw]   Rule 2
262
 
     * [xyq|cw]    Rule 4
263
 
     * [xyqn]|     Done
264
 
     */
265
 
    expect(UnicodeString("ab>x|yzacw;") +
266
 
           "za>q;" +
267
 
           "qc>r;" +
268
 
           "cw>n",
269
 
           "ab", "xyqn");
270
 
 
271
 
    /* Test categories
272
 
     */
273
 
    UErrorCode status = U_ZERO_ERROR;
274
 
    RuleBasedTransliterator t(
275
 
        "<ID>",
276
 
        UnicodeString("$dummy=").append((UChar)0xE100) +
277
 
        UnicodeString(";"
278
 
                      "$vowel=[aeiouAEIOU];"
279
 
                      "$lu=[:Lu:];"
280
 
                      "$vowel } $lu > '!';"
281
 
                      "$vowel > '&';"
282
 
                      "'!' { $lu > '^';"
283
 
                      "$lu > '*';"
284
 
                      "a > ERROR", ""),
285
 
        status);
286
 
    if (U_FAILURE(status)) {
287
 
        errln("FAIL: RBT constructor failed");
288
 
        return;
289
 
    }
290
 
    expect(t, "abcdefgABCDEFGU", "&bcd&fg!^**!^*&");
291
 
}
292
 
 
293
 
/**
294
 
 * Test inline set syntax and set variable syntax.
295
 
 */
296
 
void TransliteratorTest::TestInlineSet(void) {
297
 
    expect("{ [:Ll:] } x > y; [:Ll:] > z;", "aAbxq", "zAyzz");
298
 
    expect("a[0-9]b > qrs", "1a7b9", "1qrs9");
299
 
    
300
 
    expect(UnicodeString(
301
 
           "$digit = [0-9];"
302
 
           "$alpha = [a-zA-Z];"
303
 
           "$alphanumeric = [$digit $alpha];" // ***
304
 
           "$special = [^$alphanumeric];"     // ***
305
 
           "$alphanumeric > '-';"
306
 
           "$special > '*';", ""),
307
 
           
308
 
           "thx-1138", "---*----");
309
 
}
310
 
 
311
 
/**
312
 
 * Create some inverses and confirm that they work.  We have to be
313
 
 * careful how we do this, since the inverses will not be true
314
 
 * inverses -- we can't throw any random string at the composition
315
 
 * of the transliterators and expect the identity function.  F x
316
 
 * F' != I.  However, if we are careful about the input, we will
317
 
 * get the expected results.
318
 
 */
319
 
void TransliteratorTest::TestRuleBasedInverse(void) {
320
 
    UnicodeString RULES =
321
 
        UnicodeString("abc>zyx;") +
322
 
        "ab>yz;" +
323
 
        "bc>zx;" +
324
 
        "ca>xy;" +
325
 
        "a>x;" +
326
 
        "b>y;" +
327
 
        "c>z;" +
328
 
 
329
 
        "abc<zyx;" +
330
 
        "ab<yz;" +
331
 
        "bc<zx;" +
332
 
        "ca<xy;" +
333
 
        "a<x;" +
334
 
        "b<y;" +
335
 
        "c<z;" +
336
 
 
337
 
        "";
338
 
 
339
 
    const char* DATA[] = {
340
 
        // Careful here -- random strings will not work.  If we keep
341
 
        // the left side to the domain and the right side to the range
342
 
        // we will be okay though (left, abc; right xyz).
343
 
        "a", "x",
344
 
        "abcacab", "zyxxxyy",
345
 
        "caccb", "xyzzy",
346
 
    };
347
 
 
348
 
    int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
349
 
 
350
 
    UErrorCode status = U_ZERO_ERROR;
351
 
    RuleBasedTransliterator fwd("<ID>", RULES, status);
352
 
    RuleBasedTransliterator rev("<ID>", RULES,
353
 
                                UTRANS_REVERSE, status);
354
 
    if (U_FAILURE(status)) {
355
 
        errln("FAIL: RBT constructor failed");
356
 
        return;
357
 
    }
358
 
    for (int32_t i=0; i<DATA_length; i+=2) {
359
 
        expect(fwd, DATA[i], DATA[i+1]);
360
 
        expect(rev, DATA[i+1], DATA[i]);
361
 
    }
362
 
}
363
 
 
364
 
/**
365
 
 * Basic test of keyboard.
366
 
 */
367
 
void TransliteratorTest::TestKeyboard(void) {
368
 
    UErrorCode status = U_ZERO_ERROR;
369
 
    RuleBasedTransliterator t("<ID>",
370
 
                              UnicodeString("psch>Y;")
371
 
                              +"ps>y;"
372
 
                              +"ch>x;"
373
 
                              +"a>A;",
374
 
                              status);
375
 
    if (U_FAILURE(status)) {
376
 
        errln("FAIL: RBT constructor failed");
377
 
        return;
378
 
    }
379
 
    const char* DATA[] = {
380
 
        // insertion, buffer
381
 
        "a", "A",
382
 
        "p", "Ap",
383
 
        "s", "Aps",
384
 
        "c", "Apsc",
385
 
        "a", "AycA",
386
 
        "psch", "AycAY",
387
 
        0, "AycAY", // null means finishKeyboardTransliteration
388
 
    };
389
 
 
390
 
    keyboardAux(t, DATA, (int32_t)(sizeof(DATA)/sizeof(DATA[0])));
391
 
}
392
 
 
393
 
/**
394
 
 * Basic test of keyboard with cursor.
395
 
 */
396
 
void TransliteratorTest::TestKeyboard2(void) {
397
 
    UErrorCode status = U_ZERO_ERROR;
398
 
    RuleBasedTransliterator t("<ID>",
399
 
                              UnicodeString("ych>Y;")
400
 
                              +"ps>|y;"
401
 
                              +"ch>x;"
402
 
                              +"a>A;",
403
 
                              status);
404
 
    if (U_FAILURE(status)) {
405
 
        errln("FAIL: RBT constructor failed");
406
 
        return;
407
 
    }
408
 
    const char* DATA[] = {
409
 
        // insertion, buffer
410
 
        "a", "A",
411
 
        "p", "Ap",
412
 
        "s", "Aps", // modified for rollback - "Ay",
413
 
        "c", "Apsc", // modified for rollback - "Ayc",
414
 
        "a", "AycA",
415
 
        "p", "AycAp",
416
 
        "s", "AycAps", // modified for rollback - "AycAy",
417
 
        "c", "AycApsc", // modified for rollback - "AycAyc",
418
 
        "h", "AycAY",
419
 
        0, "AycAY", // null means finishKeyboardTransliteration
420
 
    };
421
 
 
422
 
    keyboardAux(t, DATA, (int32_t)(sizeof(DATA)/sizeof(DATA[0])));
423
 
}
424
 
 
425
 
/**
426
 
 * Test keyboard transliteration with back-replacement.
427
 
 */
428
 
void TransliteratorTest::TestKeyboard3(void) {
429
 
    // We want th>z but t>y.  Furthermore, during keyboard
430
 
    // transliteration we want t>y then yh>z if t, then h are
431
 
    // typed.
432
 
    UnicodeString RULES("t>|y;"
433
 
                        "yh>z;");
434
 
 
435
 
    const char* DATA[] = {
436
 
        // Column 1: characters to add to buffer (as if typed)
437
 
        // Column 2: expected appearance of buffer after
438
 
        //           keyboard xliteration.
439
 
        "a", "a",
440
 
        "b", "ab",
441
 
        "t", "abt", // modified for rollback - "aby",
442
 
        "c", "abyc",
443
 
        "t", "abyct", // modified for rollback - "abycy",
444
 
        "h", "abycz",
445
 
        0, "abycz", // null means finishKeyboardTransliteration
446
 
    };
447
 
 
448
 
    UErrorCode status = U_ZERO_ERROR;
449
 
    RuleBasedTransliterator t("<ID>", RULES, status);
450
 
    if (U_FAILURE(status)) {
451
 
        errln("FAIL: RBT constructor failed");
452
 
        return;
453
 
    }
454
 
    keyboardAux(t, DATA, (int32_t)(sizeof(DATA)/sizeof(DATA[0])));
455
 
}
456
 
 
457
 
void TransliteratorTest::keyboardAux(const Transliterator& t,
458
 
                                     const char* DATA[], int32_t DATA_length) {
459
 
    UErrorCode status = U_ZERO_ERROR;
460
 
    UTransPosition index={0, 0, 0, 0};
461
 
    UnicodeString s;
462
 
    for (int32_t i=0; i<DATA_length; i+=2) {
463
 
        UnicodeString log;
464
 
        if (DATA[i] != 0) {
465
 
            log = s + " + "
466
 
                + DATA[i]
467
 
                + " -> ";
468
 
            t.transliterate(s, index, DATA[i], status);
469
 
        } else {
470
 
            log = s + " => ";
471
 
            t.finishTransliteration(s, index);
472
 
        }
473
 
        // Show the start index '{' and the cursor '|'
474
 
        UnicodeString a, b, c;
475
 
        s.extractBetween(0, index.contextStart, a);
476
 
        s.extractBetween(index.contextStart, index.start, b);
477
 
        s.extractBetween(index.start, s.length(), c);
478
 
        log.append(a).
479
 
            append((UChar)LEFT_BRACE).
480
 
            append(b).
481
 
            append((UChar)PIPE).
482
 
            append(c);
483
 
        if (s == DATA[i+1] && U_SUCCESS(status)) {
484
 
            logln(log);
485
 
        } else {
486
 
            errln(UnicodeString("FAIL: ") + log + ", expected " + DATA[i+1]);
487
 
        }
488
 
    }
489
 
}
490
 
 
491
 
void TransliteratorTest::TestArabic(void) {
492
 
// Test disabled for 2.0 until new Arabic transliterator can be written.
493
 
//    /*
494
 
//    const char* DATA[] = {
495
 
//        "Arabic", "\u062a\u062a\u0645\u062a\u0639\u0020"+
496
 
//                  "\u0627\u0644\u0644\u063a\u0629\u0020"+
497
 
//                  "\u0627\u0644\u0639\u0631\u0628\u0628\u064a\u0629\u0020"+
498
 
//                  "\u0628\u0628\u0646\u0638\u0645\u0020"+
499
 
//                  "\u0643\u062a\u0627\u0628\u0628\u064a\u0629\u0020"+
500
 
//                  "\u062c\u0645\u064a\u0644\u0629",
501
 
//    };
502
 
//    */
503
 
//
504
 
//    UChar ar_raw[] = {
505
 
//        0x062a, 0x062a, 0x0645, 0x062a, 0x0639, 0x0020, 0x0627,
506
 
//        0x0644, 0x0644, 0x063a, 0x0629, 0x0020, 0x0627, 0x0644,
507
 
//        0x0639, 0x0631, 0x0628, 0x0628, 0x064a, 0x0629, 0x0020,
508
 
//        0x0628, 0x0628, 0x0646, 0x0638, 0x0645, 0x0020, 0x0643,
509
 
//        0x062a, 0x0627, 0x0628, 0x0628, 0x064a, 0x0629, 0x0020,
510
 
//        0x062c, 0x0645, 0x064a, 0x0644, 0x0629, 0
511
 
//    };
512
 
//    UnicodeString ar(ar_raw);
513
 
//    UErrorCode status=U_ZERO_ERROR;
514
 
//    UParseError parseError;
515
 
//    Transliterator *t = Transliterator::createInstance("Latin-Arabic", UTRANS_FORWARD, parseError, status);
516
 
//    if (t == 0) {
517
 
//        errln("FAIL: createInstance failed");
518
 
//        return;
519
 
//    }
520
 
//    expect(*t, "Arabic", ar);
521
 
//    delete t;
522
 
}
523
 
 
524
 
/**
525
 
 * Compose the Kana transliterator forward and reverse and try
526
 
 * some strings that should come out unchanged.
527
 
 */
528
 
void TransliteratorTest::TestCompoundKana(void) {
529
 
    UParseError parseError;
530
 
    UErrorCode status = U_ZERO_ERROR;
531
 
    Transliterator* t = Transliterator::createInstance("Latin-Hiragana;Hiragana-Latin", UTRANS_FORWARD, parseError, status);
532
 
    if (t == 0) {
533
 
        errln("FAIL: construction of Latin-Hiragana;Hiragana-Latin failed");
534
 
    } else {
535
 
        expect(*t, "aaaaa", "aaaaa");
536
 
        delete t;
537
 
    }
538
 
}
539
 
 
540
 
/**
541
 
 * Compose the hex transliterators forward and reverse.
542
 
 */
543
 
void TransliteratorTest::TestCompoundHex(void) {
544
 
    UParseError parseError;
545
 
    UErrorCode status = U_ZERO_ERROR;
546
 
    Transliterator* a = Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
547
 
    Transliterator* b = Transliterator::createInstance("Hex-Any", UTRANS_FORWARD, parseError, status);
548
 
    Transliterator* transab[] = { a, b };
549
 
    Transliterator* transba[] = { b, a };
550
 
    if (a == 0 || b == 0) {
551
 
        errln("FAIL: construction failed");
552
 
        delete a;
553
 
        delete b;
554
 
        return;
555
 
    }
556
 
    // Do some basic tests of a
557
 
    expect(*a, "01", UnicodeString("\\u0030\\u0031", ""));
558
 
    // Do some basic tests of b
559
 
    expect(*b, UnicodeString("\\u0030\\u0031", ""), "01");
560
 
 
561
 
    Transliterator* ab = new CompoundTransliterator(transab, 2);
562
 
    UnicodeString s("abcde", "");
563
 
    expect(*ab, s, s);
564
 
 
565
 
    UnicodeString str(s);
566
 
    a->transliterate(str);
567
 
    Transliterator* ba = new CompoundTransliterator(transba, 2);
568
 
    expect(*ba, str, str);
569
 
 
570
 
    delete ab;
571
 
    delete ba;
572
 
    delete a;
573
 
    delete b;
574
 
}
575
 
 
576
 
/**
577
 
 * Used by TestFiltering().
578
 
 */
579
 
class TestFilter : public UnicodeFilter {
580
 
    virtual UnicodeFunctor* clone() const {
581
 
        return new TestFilter(*this);
582
 
    }
583
 
    virtual UBool contains(UChar32 c) const {
584
 
        return c != (UChar)0x0063 /*c*/;
585
 
    }
586
 
};
587
 
 
588
 
/**
589
 
 * Do some basic tests of filtering.
590
 
 */
591
 
void TransliteratorTest::TestFiltering(void) {
592
 
    UParseError parseError;
593
 
    UErrorCode status = U_ZERO_ERROR;
594
 
    Transliterator* hex = Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
595
 
    if (hex == 0) {
596
 
        errln("FAIL: createInstance(Any-Hex) failed");
597
 
        return;
598
 
    }
599
 
    hex->adoptFilter(new TestFilter());
600
 
    UnicodeString s("abcde");
601
 
    hex->transliterate(s);
602
 
    UnicodeString exp("\\u0061\\u0062c\\u0064\\u0065", "");
603
 
    if (s == exp) {
604
 
        logln(UnicodeString("Ok:   \"") + exp + "\"");
605
 
    } else {
606
 
        logln(UnicodeString("FAIL: \"") + s + "\", wanted \"" + exp + "\"");
607
 
    }
608
 
    delete hex;
609
 
}
610
 
 
611
 
/**
612
 
 * Test anchors
613
 
 */
614
 
void TransliteratorTest::TestAnchors(void) {
615
 
    expect(UnicodeString("^a  > 0; a$ > 2 ; a > 1;", ""),
616
 
           "aaa",
617
 
           "012");
618
 
    expect(UnicodeString("$s=[z$]; $s{a>0; a}$s>2; a>1;", ""),
619
 
           "aaa",
620
 
           "012");
621
 
    expect(UnicodeString("^ab  > 01 ;"
622
 
           " ab  > |8 ;"
623
 
           "  b  > k ;"
624
 
           " 8x$ > 45 ;"
625
 
           " 8x  > 77 ;", ""),
626
 
 
627
 
           "ababbabxabx",
628
 
           "018k7745");
629
 
    expect(UnicodeString("$s = [z$] ;"
630
 
           "$s{ab    > 01 ;"
631
 
           "   ab    > |8 ;"
632
 
           "    b    > k ;"
633
 
           "   8x}$s > 45 ;"
634
 
           "   8x    > 77 ;", ""),
635
 
 
636
 
           "abzababbabxzabxabx",
637
 
           "01z018k45z01x45");
638
 
}
639
 
 
640
 
/**
641
 
 * Test pattern quoting and escape mechanisms.
642
 
 */
643
 
void TransliteratorTest::TestPatternQuoting(void) {
644
 
    // Array of 3n items
645
 
    // Each item is <rules>, <input>, <expected output>
646
 
    const UnicodeString DATA[] = {
647
 
        UnicodeString(UChar(0x4E01)) + ">'[male adult]'",
648
 
        UnicodeString(UChar(0x4E01)),
649
 
        "[male adult]"
650
 
    };
651
 
 
652
 
    for (int32_t i=0; i<3; i+=3) {
653
 
        logln(UnicodeString("Pattern: ") + prettify(DATA[i]));
654
 
        UErrorCode status = U_ZERO_ERROR;
655
 
        RuleBasedTransliterator t("<ID>", DATA[i], status);
656
 
        if (U_FAILURE(status)) {
657
 
            errln("RBT constructor failed");
658
 
        } else {
659
 
            expect(t, DATA[i+1], DATA[i+2]);
660
 
        }
661
 
    }
662
 
}
663
 
 
664
 
/**
665
 
 * Regression test for bugs found in Greek transliteration.
666
 
 */
667
 
void TransliteratorTest::TestJ277(void) {
668
 
    UErrorCode status = U_ZERO_ERROR;
669
 
    UParseError parseError;
670
 
    Transliterator *gl = Transliterator::createInstance("Greek-Latin; NFD; [:M:]Remove; NFC", UTRANS_FORWARD, parseError, status);
671
 
    if (gl == NULL) {
672
 
        errln("FAIL: createInstance(Greek-Latin) returned NULL");
673
 
        return;
674
 
    }
675
 
 
676
 
    UChar sigma = 0x3C3;
677
 
    UChar upsilon = 0x3C5;
678
 
    UChar nu = 0x3BD;
679
 
//    UChar PHI = 0x3A6;
680
 
    UChar alpha = 0x3B1;
681
 
//    UChar omega = 0x3C9;
682
 
//    UChar omicron = 0x3BF;
683
 
//    UChar epsilon = 0x3B5;
684
 
 
685
 
    // sigma upsilon nu -> syn
686
 
    UnicodeString syn;
687
 
    syn.append(sigma).append(upsilon).append(nu);
688
 
    expect(*gl, syn, "syn");
689
 
 
690
 
    // sigma alpha upsilon nu -> saun
691
 
    UnicodeString sayn;
692
 
    sayn.append(sigma).append(alpha).append(upsilon).append(nu);
693
 
    expect(*gl, sayn, "saun");
694
 
 
695
 
    // Again, using a smaller rule set
696
 
    UnicodeString rules(
697
 
                "$alpha   = \\u03B1;"
698
 
                "$nu      = \\u03BD;"
699
 
                "$sigma   = \\u03C3;"
700
 
                "$ypsilon = \\u03C5;"
701
 
                "$vowel   = [aeiouAEIOU$alpha$ypsilon];"
702
 
                "s <>           $sigma;"
703
 
                "a <>           $alpha;"
704
 
                "u <>  $vowel { $ypsilon;"
705
 
                "y <>           $ypsilon;"
706
 
                "n <>           $nu;",
707
 
                "");
708
 
    RuleBasedTransliterator mini("mini", rules, UTRANS_REVERSE, status);
709
 
    if (U_FAILURE(status)) { errln("FAIL: Transliterator constructor failed"); return; }
710
 
    expect(mini, syn, "syn");
711
 
    expect(mini, sayn, "saun");
712
 
 
713
 
    // Transliterate the Greek locale data
714
 
    Locale el("el");
715
 
    DateFormatSymbols syms(el, status);
716
 
    if (U_FAILURE(status)) { errln("FAIL: Transliterator constructor failed"); return; }
717
 
    int32_t i, count;
718
 
    const UnicodeString* data = syms.getMonths(count);
719
 
    for (i=0; i<count; ++i) {
720
 
        if (data[i].length() == 0) {
721
 
            continue;
722
 
        }
723
 
        UnicodeString out(data[i]);
724
 
        gl->transliterate(out);
725
 
        UBool ok = TRUE;
726
 
        if (data[i].length() >= 2 && out.length() >= 2 &&
727
 
            u_isupper(data[i].charAt(0)) && u_islower(data[i].charAt(1))) {
728
 
            if (!(u_isupper(out.charAt(0)) && u_islower(out.charAt(1)))) {
729
 
                ok = FALSE;
730
 
            }
731
 
        }
732
 
        if (ok) {
733
 
            logln(prettify(data[i] + " -> " + out));
734
 
        } else {
735
 
            errln(UnicodeString("FAIL: ") + prettify(data[i] + " -> " + out));
736
 
        }
737
 
    }
738
 
 
739
 
    delete gl;
740
 
}
741
 
 
742
 
/**
743
 
 * Prefix, suffix support in hex transliterators
744
 
 */
745
 
void TransliteratorTest::TestJ243(void) {
746
 
    UErrorCode status = U_ZERO_ERROR;
747
 
    
748
 
#if !defined(HPUX)
749
 
    // Test default Hex-Any, which should handle
750
 
    // \u, \U, u+, and U+
751
 
    HexToUnicodeTransliterator hex;
752
 
    expect(hex, UnicodeString("\\u0041+\\U0042,u+0043uu+0044z", ""), "A+B,CuDz");
753
 
    // Try a custom Hex-Unicode
754
 
    // \uXXXX and &#xXXXX;
755
 
    status = U_ZERO_ERROR;
756
 
    HexToUnicodeTransliterator hex2(UnicodeString("\\\\u###0;&\\#x###0\\;", ""), status);
757
 
    expect(hex2, UnicodeString("\\u61\\u062\\u0063\\u00645\\u66x&#x30;&#x031;&#x0032;&#x00033;", ""),
758
 
           "abcd5fx012&#x00033;");
759
 
    // Try custom Any-Hex (default is tested elsewhere)
760
 
    status = U_ZERO_ERROR;
761
 
    UnicodeToHexTransliterator hex3(UnicodeString("&\\#x###0;", ""), status);
762
 
    expect(hex3, "012", "&#x30;&#x31;&#x32;");
763
 
#endif
764
 
}
765
 
 
766
 
/**
767
 
 * Parsers need better syntax error messages.
768
 
 */
769
 
void TransliteratorTest::TestJ329(void) {
770
 
    
771
 
    struct { UBool containsErrors; const char* rule; } DATA[] = {
772
 
        { FALSE, "a > b; c > d" },
773
 
        { TRUE,  "a > b; no operator; c > d" },
774
 
    };
775
 
    int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
776
 
 
777
 
    for (int32_t i=0; i<DATA_length; ++i) {
778
 
        UErrorCode status = U_ZERO_ERROR;
779
 
        UParseError parseError;
780
 
        RuleBasedTransliterator rbt("<ID>",
781
 
                                    DATA[i].rule,
782
 
                                    UTRANS_FORWARD,
783
 
                                    0,
784
 
                                    parseError,
785
 
                                    status);
786
 
        UBool gotError = U_FAILURE(status);
787
 
        UnicodeString desc(DATA[i].rule);
788
 
        desc.append(gotError ? " -> error" : " -> no error");
789
 
        if (gotError) {
790
 
            desc = desc + ", ParseError code=" + u_errorName(status) +
791
 
                " line=" + parseError.line +
792
 
                " offset=" + parseError.offset +
793
 
                " context=" + parseError.preContext;
794
 
        }
795
 
        if (gotError == DATA[i].containsErrors) {
796
 
            logln(UnicodeString("Ok:   ") + desc);
797
 
        } else {
798
 
            errln(UnicodeString("FAIL: ") + desc);
799
 
        }
800
 
    }
801
 
}
802
 
 
803
 
/**
804
 
 * Test segments and segment references.
805
 
 */
806
 
void TransliteratorTest::TestSegments(void) {
807
 
    // Array of 3n items
808
 
    // Each item is <rules>, <input>, <expected output>
809
 
    UnicodeString DATA[] = {
810
 
        "([a-z]) '.' ([0-9]) > $2 '-' $1",
811
 
        "abc.123.xyz.456",
812
 
        "ab1-c23.xy4-z56",
813
 
 
814
 
        // nested
815
 
        "(([a-z])([0-9])) > $1 '.' $2 '.' $3;",
816
 
        "a1 b2",
817
 
        "a1.a.1 b2.b.2",
818
 
    };
819
 
    int32_t DATA_length = (int32_t)(sizeof(DATA)/sizeof(*DATA));
820
 
 
821
 
    for (int32_t i=0; i<DATA_length; i+=3) {
822
 
        logln("Pattern: " + prettify(DATA[i]));
823
 
        UErrorCode status = U_ZERO_ERROR;
824
 
        RuleBasedTransliterator t("ID", DATA[i], status);
825
 
        if (U_FAILURE(status)) {
826
 
            errln("FAIL: RBT constructor");
827
 
        } else {
828
 
            expect(t, DATA[i+1], DATA[i+2]);
829
 
        }
830
 
    }
831
 
}
832
 
 
833
 
/**
834
 
 * Test cursor positioning outside of the key
835
 
 */
836
 
void TransliteratorTest::TestCursorOffset(void) {
837
 
    // Array of 3n items
838
 
    // Each item is <rules>, <input>, <expected output>
839
 
    UnicodeString DATA[] = {
840
 
        "pre {alpha} post > | @ ALPHA ;"
841
 
        "eALPHA > beta ;"
842
 
        "pre {beta} post > BETA @@ | ;"
843
 
        "post > xyz",
844
 
 
845
 
        "prealphapost prebetapost",
846
 
 
847
 
        "prbetaxyz preBETApost",
848
 
    };
849
 
    int32_t DATA_length = (int32_t)(sizeof(DATA)/sizeof(*DATA));
850
 
 
851
 
    for (int32_t i=0; i<DATA_length; i+=3) {
852
 
        logln("Pattern: " + prettify(DATA[i]));
853
 
        UErrorCode status = U_ZERO_ERROR;
854
 
        RuleBasedTransliterator t("<ID>", DATA[i], status);
855
 
        if (U_FAILURE(status)) {
856
 
            errln("FAIL: RBT constructor");
857
 
        } else {
858
 
            expect(t, DATA[i+1], DATA[i+2]);
859
 
        }
860
 
    }
861
 
}
862
 
 
863
 
/**
864
 
 * Test zero length and > 1 char length variable values.  Test
865
 
 * use of variable refs in UnicodeSets.
866
 
 */
867
 
void TransliteratorTest::TestArbitraryVariableValues(void) {
868
 
    // Array of 3n items
869
 
    // Each item is <rules>, <input>, <expected output>
870
 
    UnicodeString DATA[] = {
871
 
        "$abe = ab;"
872
 
        "$pat = x[yY]z;"
873
 
        "$ll  = 'a-z';"
874
 
        "$llZ = [$ll];"
875
 
        "$llY = [$ll$pat];"
876
 
        "$emp = ;"
877
 
 
878
 
        "$abe > ABE;"
879
 
        "$pat > END;"
880
 
        "$llZ > 1;"
881
 
        "$llY > 2;"
882
 
        "7$emp 8 > 9;"
883
 
        "",
884
 
 
885
 
        "ab xYzxyz stY78",
886
 
        "ABE ENDEND 1129",
887
 
    };
888
 
    int32_t DATA_length = (int32_t)(sizeof(DATA)/sizeof(*DATA));
889
 
 
890
 
    for (int32_t i=0; i<DATA_length; i+=3) {
891
 
        logln("Pattern: " + prettify(DATA[i]));
892
 
        UErrorCode status = U_ZERO_ERROR;
893
 
        RuleBasedTransliterator t("<ID>", DATA[i], status);
894
 
        if (U_FAILURE(status)) {
895
 
            errln("FAIL: RBT constructor");
896
 
        } else {
897
 
            expect(t, DATA[i+1], DATA[i+2]);
898
 
        }
899
 
    }
900
 
}
901
 
 
902
 
/**
903
 
 * Confirm that the contextStart, contextLimit, start, and limit
904
 
 * behave correctly. J474.
905
 
 */
906
 
void TransliteratorTest::TestPositionHandling(void) {
907
 
    // Array of 3n items
908
 
    // Each item is <rules>, <input>, <expected output>
909
 
    const char* DATA[] = {
910
 
        "a{t} > SS ; {t}b > UU ; {t} > TT ;",
911
 
        "xtat txtb", // pos 0,9,0,9
912
 
        "xTTaSS TTxUUb",
913
 
 
914
 
        "a{t} > SS ; {t}b > UU ; {t} > TT ; a > A ; b > B ;",
915
 
        "xtat txtb", // pos 2,9,3,8
916
 
        "xtaSS TTxUUb",
917
 
 
918
 
        "a{t} > SS ; {t}b > UU ; {t} > TT ; a > A ; b > B ;",
919
 
        "xtat txtb", // pos 3,8,3,8
920
 
        "xtaTT TTxTTb",
921
 
    };
922
 
 
923
 
    // Array of 4n positions -- these go with the DATA array
924
 
    // They are: contextStart, contextLimit, start, limit
925
 
    int32_t POS[] = {
926
 
        0, 9, 0, 9,
927
 
        2, 9, 3, 8,
928
 
        3, 8, 3, 8,
929
 
    };
930
 
 
931
 
    int32_t n = (int32_t)(sizeof(DATA) / sizeof(DATA[0])) / 3;
932
 
    for (int32_t i=0; i<n; i++) {
933
 
        UErrorCode status = U_ZERO_ERROR;
934
 
        Transliterator *t = new RuleBasedTransliterator("<ID>",
935
 
                                                        DATA[3*i], status);
936
 
        if (U_FAILURE(status)) {
937
 
            delete t;
938
 
            errln("FAIL: RBT constructor");
939
 
            return;
940
 
        }
941
 
        UTransPosition pos;
942
 
        pos.contextStart= POS[4*i];
943
 
        pos.contextLimit = POS[4*i+1];
944
 
        pos.start = POS[4*i+2];
945
 
        pos.limit = POS[4*i+3];
946
 
        UnicodeString rsource(DATA[3*i+1]);
947
 
        t->transliterate(rsource, pos, status);
948
 
        if (U_FAILURE(status)) {
949
 
            delete t;
950
 
            errln("FAIL: transliterate");
951
 
            return;
952
 
        }
953
 
        t->finishTransliteration(rsource, pos);
954
 
        expectAux(DATA[3*i],
955
 
                  DATA[3*i+1],
956
 
                  rsource,
957
 
                  DATA[3*i+2]);
958
 
        delete t;
959
 
    }
960
 
}
961
 
 
962
 
/**
963
 
 * Test the Hiragana-Katakana transliterator.
964
 
 */
965
 
void TransliteratorTest::TestHiraganaKatakana(void) {
966
 
    UParseError parseError;
967
 
    UErrorCode status = U_ZERO_ERROR;
968
 
    Transliterator* hk = Transliterator::createInstance("Hiragana-Katakana", UTRANS_FORWARD, parseError, status);
969
 
    Transliterator* kh = Transliterator::createInstance("Katakana-Hiragana", UTRANS_FORWARD, parseError, status);
970
 
    if (hk == 0 || kh == 0) {
971
 
        errln("FAIL: createInstance failed");
972
 
        delete hk;
973
 
        delete kh;
974
 
        return;
975
 
    }
976
 
 
977
 
    // Array of 3n items
978
 
    // Each item is "hk"|"kh"|"both", <Hiragana>, <Katakana>
979
 
    const char* DATA[] = {
980
 
        "both",
981
 
        "\\u3042\\u3090\\u3099\\u3092\\u3050",
982
 
        "\\u30A2\\u30F8\\u30F2\\u30B0",
983
 
 
984
 
        "kh",
985
 
        "\\u307C\\u3051\\u3060\\u3042\\u3093\\u30FC",
986
 
        "\\u30DC\\u30F6\\u30C0\\u30FC\\u30F3\\u30FC",
987
 
    };
988
 
    int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
989
 
 
990
 
    for (int32_t i=0; i<DATA_length; i+=3) {
991
 
        UnicodeString h = CharsToUnicodeString(DATA[i+1]);
992
 
        UnicodeString k = CharsToUnicodeString(DATA[i+2]);
993
 
        switch (*DATA[i]) {
994
 
        case 0x68: //'h': // Hiragana-Katakana
995
 
            expect(*hk, h, k);
996
 
            break;
997
 
        case 0x6B: //'k': // Katakana-Hiragana
998
 
            expect(*kh, k, h);
999
 
            break;
1000
 
        case 0x62: //'b': // both
1001
 
            expect(*hk, h, k);
1002
 
            expect(*kh, k, h);
1003
 
            break;
1004
 
        }
1005
 
    }
1006
 
    delete hk;
1007
 
    delete kh;
1008
 
}
1009
 
 
1010
 
/**
1011
 
 * Test cloning / copy constructor of RBT.
1012
 
 */
1013
 
void TransliteratorTest::TestCopyJ476(void) {
1014
 
    // The real test here is what happens when the destructors are
1015
 
    // called.  So we let one object get destructed, and check to
1016
 
    // see that its copy still works.
1017
 
    RuleBasedTransliterator *t2 = 0;
1018
 
    {
1019
 
        UErrorCode status = U_ZERO_ERROR;
1020
 
        RuleBasedTransliterator t1("t1", "a>A;b>B;", status);
1021
 
        if (U_FAILURE(status)) {
1022
 
            errln("FAIL: RBT constructor");
1023
 
            return;
1024
 
        }
1025
 
        t2 = new RuleBasedTransliterator(t1);
1026
 
        expect(t1, "abc", "ABc");
1027
 
    }
1028
 
    expect(*t2, "abc", "ABc");
1029
 
    delete t2;
1030
 
}
1031
 
 
1032
 
/**
1033
 
 * Test inter-Indic transliterators.  These are composed.
1034
 
 * ICU4C Jitterbug 483.
1035
 
 */
1036
 
void TransliteratorTest::TestInterIndic(void) {
1037
 
    UnicodeString ID("Devanagari-Gujarati", "");
1038
 
    UErrorCode status = U_ZERO_ERROR;
1039
 
    UParseError parseError;
1040
 
    Transliterator* dg = Transliterator::createInstance(ID, UTRANS_FORWARD, parseError, status);
1041
 
    if (dg == 0) {
1042
 
        errln("FAIL: createInstance(" + ID + ") returned NULL");
1043
 
        return;
1044
 
    }
1045
 
    UnicodeString id = dg->getID();
1046
 
    if (id != ID) {
1047
 
        errln("FAIL: createInstance(" + ID + ")->getID() => " + id);
1048
 
    }
1049
 
    UnicodeString dev = CharsToUnicodeString("\\u0901\\u090B\\u0925");
1050
 
    UnicodeString guj = CharsToUnicodeString("\\u0A81\\u0A8B\\u0AA5");
1051
 
    expect(*dg, dev, guj);
1052
 
    delete dg;
1053
 
}
1054
 
 
1055
 
/**
1056
 
 * Test filter syntax in IDs. (J918)
1057
 
 */
1058
 
void TransliteratorTest::TestFilterIDs(void) {
1059
 
    // Array of 3n strings:
1060
 
    // <id>, <inverse id>, <input>, <expected output>
1061
 
    const char* DATA[] = {
1062
 
        "[aeiou]Any-Hex", // ID
1063
 
        "[aeiou]Hex-Any", // expected inverse ID
1064
 
        "quizzical",      // src
1065
 
        "q\\u0075\\u0069zz\\u0069c\\u0061l", // expected ID.translit(src)
1066
 
        
1067
 
        "[aeiou]Any-Hex;[^5]Hex-Any",
1068
 
        "[^5]Any-Hex;[aeiou]Hex-Any",
1069
 
        "quizzical",
1070
 
        "q\\u0075izzical",
1071
 
        
1072
 
        "[abc]Null",
1073
 
        "[abc]Null",
1074
 
        "xyz",
1075
 
        "xyz",
1076
 
    };
1077
 
    enum { DATA_length = sizeof(DATA) / sizeof(DATA[0]) };
1078
 
 
1079
 
    for (int i=0; i<DATA_length; i+=4) {
1080
 
        UnicodeString ID(DATA[i], "");
1081
 
        UnicodeString uID(DATA[i+1], "");
1082
 
        UnicodeString data2(DATA[i+2], "");
1083
 
        UnicodeString data3(DATA[i+3], "");
1084
 
        UParseError parseError;
1085
 
        UErrorCode status = U_ZERO_ERROR;
1086
 
        Transliterator *t = Transliterator::createInstance(ID, UTRANS_FORWARD, parseError, status);
1087
 
        if (t == 0) {
1088
 
            errln("FAIL: createInstance(" + ID + ") returned NULL");
1089
 
            return;
1090
 
        }
1091
 
        expect(*t, data2, data3);
1092
 
 
1093
 
        // Check the ID
1094
 
        if (ID != t->getID()) {
1095
 
            errln("FAIL: createInstance(" + ID + ").getID() => " +
1096
 
                  t->getID());
1097
 
        }
1098
 
 
1099
 
        // Check the inverse
1100
 
        Transliterator *u = t->createInverse(status);
1101
 
        if (u == 0) {
1102
 
            errln("FAIL: " + ID + ".createInverse() returned NULL");
1103
 
        } else if (u->getID() != uID) {
1104
 
            errln("FAIL: " + ID + ".createInverse().getID() => " +
1105
 
                  u->getID() + ", expected " + uID);
1106
 
        }
1107
 
 
1108
 
        delete t;
1109
 
        delete u;
1110
 
    }
1111
 
}
1112
 
 
1113
 
/**
1114
 
 * Test the case mapping transliterators.
1115
 
 */
1116
 
void TransliteratorTest::TestCaseMap(void) {
1117
 
    UParseError parseError;
1118
 
    UErrorCode status = U_ZERO_ERROR;
1119
 
    Transliterator* toUpper =
1120
 
        Transliterator::createInstance("Any-Upper[^xyzXYZ]", UTRANS_FORWARD, parseError, status);
1121
 
    Transliterator* toLower =
1122
 
        Transliterator::createInstance("Any-Lower[^xyzXYZ]", UTRANS_FORWARD, parseError, status);
1123
 
    Transliterator* toTitle =
1124
 
        Transliterator::createInstance("Any-Title[^xyzXYZ]", UTRANS_FORWARD, parseError, status);
1125
 
    if (toUpper==0 || toLower==0 || toTitle==0) {
1126
 
        errln("FAIL: createInstance returned NULL");
1127
 
        delete toUpper;
1128
 
        delete toLower;
1129
 
        delete toTitle;
1130
 
        return;
1131
 
    }
1132
 
 
1133
 
    expect(*toUpper, "The quick brown fox jumped over the lazy dogs.",
1134
 
           "THE QUICK BROWN FOx JUMPED OVER THE LAzy DOGS.");
1135
 
    expect(*toLower, "The quIck brown fOX jUMPED OVER THE LAzY dogs.",
1136
 
           "the quick brown foX jumped over the lazY dogs.");
1137
 
    expect(*toTitle, "the quick brown foX can't jump over the laZy dogs.",
1138
 
           "The Quick Brown FoX Can't Jump Over The LaZy Dogs.");
1139
 
 
1140
 
    delete toUpper;
1141
 
    delete toLower;
1142
 
    delete toTitle;
1143
 
}
1144
 
 
1145
 
/**
1146
 
 * Test the name mapping transliterators.
1147
 
 */
1148
 
void TransliteratorTest::TestNameMap(void) {
1149
 
    UParseError parseError;
1150
 
    UErrorCode status = U_ZERO_ERROR;
1151
 
    Transliterator* uni2name =
1152
 
        Transliterator::createInstance("Any-Name[^abc]", UTRANS_FORWARD, parseError, status);
1153
 
    Transliterator* name2uni =
1154
 
        Transliterator::createInstance("Name-Any", UTRANS_FORWARD, parseError, status);
1155
 
    if (uni2name==0 || name2uni==0) {
1156
 
        errln("FAIL: createInstance returned NULL");
1157
 
        delete uni2name;
1158
 
        delete name2uni;
1159
 
        return;
1160
 
    }
1161
 
 
1162
 
    expect(*uni2name, CharsToUnicodeString("\\u00A0abc\\u4E01\\u00B5\\u0A81\\uFFFD\\u0004\\u0009\\u0081\\uFFFF"),
1163
 
           CharsToUnicodeString("{NO-BREAK SPACE}abc{CJK UNIFIED IDEOGRAPH-4E01}{MICRO SIGN}{GUJARATI SIGN CANDRABINDU}{REPLACEMENT CHARACTER}{END OF TRANSMISSION}{HORIZONTAL TABULATION}{<control-0081>}{<noncharacter-FFFF>}"));
1164
 
    expect(*name2uni, "{ NO-BREAK SPACE}abc{  CJK UNIFIED  IDEOGRAPH-4E01  }{x{MICRO SIGN}{GUJARATI SIGN CANDRABINDU}{REPLACEMENT CHARACTER}{END OF TRANSMISSION}{HORIZONTAL TABULATION}{<control-0081>}{<noncharacter-FFFF>}{<control-0004>}{",
1165
 
           CharsToUnicodeString("\\u00A0abc\\u4E01{x\\u00B5\\u0A81\\uFFFD\\u0004\\u0009\\u0081\\uFFFF\\u0004{"));
1166
 
 
1167
 
    delete uni2name;
1168
 
    delete name2uni;
1169
 
}
1170
 
 
1171
 
/**
1172
 
 * Test liberalized ID syntax.  1006c
1173
 
 */
1174
 
void TransliteratorTest::TestLiberalizedID(void) {
1175
 
    // Some test cases have an expected getID() value of NULL.  This
1176
 
    // means I have disabled the test case for now.  This stuff is
1177
 
    // still under development, and I haven't decided whether to make
1178
 
    // getID() return canonical case yet.  It will all get rewritten
1179
 
    // with the move to Source-Target/Variant IDs anyway. [aliu]
1180
 
    const char* DATA[] = {
1181
 
        "latin-greek", NULL /*"Latin-Greek"*/, "case insensitivity",
1182
 
        "  Null  ", "Null", "whitespace",
1183
 
        " Latin[a-z]-Greek  ", "[a-z]Latin-Greek", "inline filter",
1184
 
        "  null  ; latin-greek  ", NULL /*"Null;Latin-Greek"*/, "compound whitespace",
1185
 
    };
1186
 
    const int32_t DATA_length = sizeof(DATA)/sizeof(DATA[0]);
1187
 
    UParseError parseError;
1188
 
    UErrorCode status= U_ZERO_ERROR;
1189
 
    for (int32_t i=0; i<DATA_length; i+=3) {
1190
 
        Transliterator *t = Transliterator::createInstance(DATA[i], UTRANS_FORWARD, parseError, status);
1191
 
        if (t == 0) {
1192
 
            errln(UnicodeString("FAIL: ") + DATA[i+2] +
1193
 
                  " cannot create ID \"" + DATA[i] + "\"");
1194
 
        } else {
1195
 
            UnicodeString exp;
1196
 
            if (DATA[i+1]) {
1197
 
                exp = UnicodeString(DATA[i+1], "");
1198
 
            }
1199
 
            // Don't worry about getID() if the expected char*
1200
 
            // is NULL -- see above.
1201
 
            if (exp.length() == 0 || exp == t->getID()) {
1202
 
                logln(UnicodeString("Ok: ") + DATA[i+2] +
1203
 
                      " create ID \"" + DATA[i] + "\" => \"" +
1204
 
                      exp + "\"");
1205
 
            } else {
1206
 
                errln(UnicodeString("FAIL: ") + DATA[i+2] +
1207
 
                      " create ID \"" + DATA[i] + "\" => \"" +
1208
 
                      t->getID() + "\", exp \"" + exp + "\"");
1209
 
            }
1210
 
            delete t;
1211
 
        }
1212
 
    }
1213
 
}
1214
 
 
1215
 
/* test for Jitterbug 912 */
1216
 
void TransliteratorTest::TestCreateInstance(){
1217
 
    UParseError err;
1218
 
    UErrorCode status = U_ZERO_ERROR;
1219
 
    Transliterator* myTrans = Transliterator::createInstance(UnicodeString("Latin-Hangul"),UTRANS_REVERSE,err,status);
1220
 
    if (myTrans == 0) {
1221
 
        errln("FAIL: createInstance failed");
1222
 
        return;
1223
 
    }
1224
 
    UnicodeString newID =myTrans->getID();
1225
 
    if(newID!=UnicodeString("Hangul-Latin")){
1226
 
        errln(UnicodeString("Test for Jitterbug 912 Transliterator::createInstance(id,UTRANS_REVERSE) failed"));
1227
 
    }
1228
 
    delete myTrans;
1229
 
}
1230
 
 
1231
 
/**
1232
 
 * Test the normalization transliterator.
1233
 
 */
1234
 
void TransliteratorTest::TestNormalizationTransliterator() {
1235
 
    // THE FOLLOWING TWO TABLES ARE COPIED FROM com.ibm.test.normalizer.BasicTest
1236
 
    // PLEASE KEEP THEM IN SYNC WITH BasicTest.
1237
 
    const char* CANON[] = {
1238
 
        // Input               Decomposed            Composed
1239
 
        "cat",                "cat",                "cat"               ,
1240
 
        "\\u00e0ardvark",      "a\\u0300ardvark",     "\\u00e0ardvark"    ,
1241
 
 
1242
 
        "\\u1e0a",             "D\\u0307",            "\\u1e0a"            , // D-dot_above
1243
 
        "D\\u0307",            "D\\u0307",            "\\u1e0a"            , // D dot_above
1244
 
 
1245
 
        "\\u1e0c\\u0307",       "D\\u0323\\u0307",      "\\u1e0c\\u0307"      , // D-dot_below dot_above
1246
 
        "\\u1e0a\\u0323",       "D\\u0323\\u0307",      "\\u1e0c\\u0307"      , // D-dot_above dot_below
1247
 
        "D\\u0307\\u0323",      "D\\u0323\\u0307",      "\\u1e0c\\u0307"      , // D dot_below dot_above
1248
 
 
1249
 
        "\\u1e10\\u0307\\u0323", "D\\u0327\\u0323\\u0307","\\u1e10\\u0323\\u0307", // D dot_below cedilla dot_above
1250
 
        "D\\u0307\\u0328\\u0323","D\\u0328\\u0323\\u0307","\\u1e0c\\u0328\\u0307", // D dot_above ogonek dot_below
1251
 
 
1252
 
        "\\u1E14",             "E\\u0304\\u0300",      "\\u1E14"            , // E-macron-grave
1253
 
        "\\u0112\\u0300",       "E\\u0304\\u0300",      "\\u1E14"            , // E-macron + grave
1254
 
        "\\u00c8\\u0304",       "E\\u0300\\u0304",      "\\u00c8\\u0304"      , // E-grave + macron
1255
 
 
1256
 
        "\\u212b",             "A\\u030a",            "\\u00c5"            , // angstrom_sign
1257
 
        "\\u00c5",             "A\\u030a",            "\\u00c5"            , // A-ring
1258
 
 
1259
 
        "\\u00fdffin",         "y\\u0301ffin",        "\\u00fdffin"        ,    //updated with 3.0
1260
 
        "\\u00fd\\uFB03n",      "y\\u0301\\uFB03n",     "\\u00fd\\uFB03n"     , //updated with 3.0
1261
 
 
1262
 
        "Henry IV",           "Henry IV",           "Henry IV"          ,
1263
 
        "Henry \\u2163",       "Henry \\u2163",       "Henry \\u2163"      ,
1264
 
 
1265
 
        "\\u30AC",             "\\u30AB\\u3099",       "\\u30AC"            , // ga (Katakana)
1266
 
        "\\u30AB\\u3099",       "\\u30AB\\u3099",       "\\u30AC"            , // ka + ten
1267
 
        "\\uFF76\\uFF9E",       "\\uFF76\\uFF9E",       "\\uFF76\\uFF9E"      , // hw_ka + hw_ten
1268
 
        "\\u30AB\\uFF9E",       "\\u30AB\\uFF9E",       "\\u30AB\\uFF9E"      , // ka + hw_ten
1269
 
        "\\uFF76\\u3099",       "\\uFF76\\u3099",       "\\uFF76\\u3099"      , // hw_ka + ten
1270
 
 
1271
 
        "A\\u0300\\u0316",      "A\\u0316\\u0300",      "\\u00C0\\u0316"      ,
1272
 
        0 // end
1273
 
    };
1274
 
 
1275
 
    const char* COMPAT[] = {
1276
 
        // Input               Decomposed            Composed
1277
 
        "\\uFB4f",             "\\u05D0\\u05DC",       "\\u05D0\\u05DC"     , // Alef-Lamed vs. Alef, Lamed
1278
 
 
1279
 
        "\\u00fdffin",         "y\\u0301ffin",        "\\u00fdffin"        ,    //updated for 3.0
1280
 
        "\\u00fd\\uFB03n",      "y\\u0301ffin",        "\\u00fdffin"        , // ffi ligature -> f + f + i
1281
 
 
1282
 
        "Henry IV",           "Henry IV",           "Henry IV"          ,
1283
 
        "Henry \\u2163",       "Henry IV",           "Henry IV"          ,
1284
 
 
1285
 
        "\\u30AC",             "\\u30AB\\u3099",       "\\u30AC"            , // ga (Katakana)
1286
 
        "\\u30AB\\u3099",       "\\u30AB\\u3099",       "\\u30AC"            , // ka + ten
1287
 
 
1288
 
        "\\uFF76\\u3099",       "\\u30AB\\u3099",       "\\u30AC"            , // hw_ka + ten
1289
 
        0 // end
1290
 
    };
1291
 
 
1292
 
    int32_t i;
1293
 
    UParseError parseError;
1294
 
    UErrorCode status = U_ZERO_ERROR;
1295
 
    Transliterator* NFD = Transliterator::createInstance("NFD", UTRANS_FORWARD, parseError, status);
1296
 
    Transliterator* NFC = Transliterator::createInstance("NFC", UTRANS_FORWARD, parseError, status);
1297
 
    if (!NFD || !NFC) {
1298
 
        errln("FAIL: createInstance failed");
1299
 
        delete NFD;
1300
 
        delete NFC;
1301
 
        return;
1302
 
    }
1303
 
    for (i=0; CANON[i]; i+=3) {
1304
 
        UnicodeString in = CharsToUnicodeString(CANON[i]);
1305
 
        UnicodeString expd = CharsToUnicodeString(CANON[i+1]);
1306
 
        UnicodeString expc = CharsToUnicodeString(CANON[i+2]);
1307
 
        expect(*NFD, in, expd);
1308
 
        expect(*NFC, in, expc);
1309
 
    }
1310
 
    delete NFD;
1311
 
    delete NFC;
1312
 
 
1313
 
    Transliterator* NFKD = Transliterator::createInstance("NFKD", UTRANS_FORWARD, parseError, status);
1314
 
    Transliterator* NFKC = Transliterator::createInstance("NFKC", UTRANS_FORWARD, parseError, status);
1315
 
    if (!NFKD || !NFKC) {
1316
 
        errln("FAIL: createInstance failed");
1317
 
        delete NFKD;
1318
 
        delete NFKC;
1319
 
        return;
1320
 
    }
1321
 
    for (i=0; COMPAT[i]; i+=3) {
1322
 
        UnicodeString in = CharsToUnicodeString(COMPAT[i]);
1323
 
        UnicodeString expkd = CharsToUnicodeString(COMPAT[i+1]);
1324
 
        UnicodeString expkc = CharsToUnicodeString(COMPAT[i+2]);
1325
 
        expect(*NFKD, in, expkd);
1326
 
        expect(*NFKC, in, expkc);
1327
 
    }
1328
 
    delete NFKD;
1329
 
    delete NFKC;
1330
 
 
1331
 
    UParseError pe;
1332
 
    status = U_ZERO_ERROR;
1333
 
    Transliterator *t = Transliterator::createInstance("NFD; [x]Remove",
1334
 
                                                       UTRANS_FORWARD,
1335
 
                                                       pe, status);
1336
 
    if (t == 0) {
1337
 
        errln("FAIL: createInstance failed");
1338
 
    }
1339
 
    expect(*t, CharsToUnicodeString("\\u010dx"),
1340
 
           CharsToUnicodeString("c\\u030C"));
1341
 
    delete t;
1342
 
}
1343
 
 
1344
 
/**
1345
 
 * Test compound RBT rules.
1346
 
 */
1347
 
void TransliteratorTest::TestCompoundRBT(void) {
1348
 
    // Careful with spacing and ';' here:  Phrase this exactly
1349
 
    // as toRules() is going to return it.  If toRules() changes
1350
 
    // with regard to spacing or ';', then adjust this string.
1351
 
    UnicodeString rule("::Hex-Any;\n"
1352
 
                       "::Any-Lower;\n"
1353
 
                       "a > '.A.';\n"
1354
 
                       "b > '.B.';\n"
1355
 
                       "::[^t]Any-Upper;", "");
1356
 
    UParseError parseError;
1357
 
    UErrorCode status = U_ZERO_ERROR;
1358
 
    Transliterator *t = Transliterator::createFromRules("Test", rule, UTRANS_FORWARD, parseError, status);
1359
 
    if (t == 0) {
1360
 
        errln("FAIL: createFromRules failed");
1361
 
        return;
1362
 
    }
1363
 
    expect(*t, "\\u0043at in the hat, bat on the mat",
1364
 
           "C.A.t IN tHE H.A.t, .B..A.t ON tHE M.A.t");
1365
 
    UnicodeString r;
1366
 
    t->toRules(r, TRUE);
1367
 
    if (r == rule) {
1368
 
        logln((UnicodeString)"OK: toRules() => " + r);
1369
 
    } else {
1370
 
        errln((UnicodeString)"FAIL: toRules() => " + r +
1371
 
              ", expected " + rule);
1372
 
    }
1373
 
    delete t;
1374
 
 
1375
 
    // Now test toRules
1376
 
    t = Transliterator::createInstance("Greek-Latin; Latin-Cyrillic", UTRANS_FORWARD, parseError, status);
1377
 
    if (t == 0) {
1378
 
        errln("FAIL: createInstance failed");
1379
 
        return;
1380
 
    }
1381
 
    UnicodeString exp("::Greek-Latin;\n::Latin-Cyrillic;");
1382
 
    t->toRules(r, TRUE);
1383
 
    if (r != exp) {
1384
 
        errln((UnicodeString)"FAIL: toRules() => " + r +
1385
 
              ", expected " + exp);
1386
 
    } else {
1387
 
        logln((UnicodeString)"OK: toRules() => " + r);
1388
 
    }
1389
 
    delete t;
1390
 
 
1391
 
    // Round trip the result of toRules
1392
 
    t = Transliterator::createFromRules("Test", r, UTRANS_FORWARD, parseError, status);
1393
 
    if (t == 0) {
1394
 
        errln("FAIL: createFromRules #2 failed");
1395
 
        return;
1396
 
    } else {
1397
 
        logln((UnicodeString)"OK: createFromRules(" + r + ") succeeded");
1398
 
    }
1399
 
 
1400
 
    // Test toRules again
1401
 
    t->toRules(r, TRUE);
1402
 
    if (r != exp) {
1403
 
        errln((UnicodeString)"FAIL: toRules() => " + r +
1404
 
              ", expected " + exp);
1405
 
    } else {
1406
 
        logln((UnicodeString)"OK: toRules() => " + r);
1407
 
    }
1408
 
 
1409
 
    delete t;
1410
 
 
1411
 
    // Test Foo(Bar) IDs.  Careful with spacing in id; make it conform
1412
 
    // to what the regenerated ID will look like.
1413
 
    UnicodeString id("Upper(Lower);(NFKC)", "");
1414
 
    t = Transliterator::createInstance(id, UTRANS_FORWARD, parseError, status);
1415
 
    if (t == 0) {
1416
 
        errln("FAIL: createInstance #2 failed");
1417
 
        return;
1418
 
    }
1419
 
    if (t->getID() == id) {
1420
 
        logln((UnicodeString)"OK: created " + id);
1421
 
    } else {
1422
 
        errln((UnicodeString)"FAIL: createInstance(" + id +
1423
 
              ").getID() => " + t->getID());
1424
 
    }
1425
 
 
1426
 
    Transliterator *u = t->createInverse(status);
1427
 
    if (u == 0) {
1428
 
        errln("FAIL: createInverse failed");
1429
 
        delete t;
1430
 
        return;
1431
 
    }
1432
 
    exp = "NFKC();Lower(Upper)";
1433
 
    if (u->getID() == exp) {
1434
 
        logln((UnicodeString)"OK: createInverse(" + id + ") => " +
1435
 
              u->getID());
1436
 
    } else {
1437
 
        errln((UnicodeString)"FAIL: createInverse(" + id + ") => " +
1438
 
              u->getID());
1439
 
    }
1440
 
    delete t;
1441
 
    delete u;
1442
 
}
1443
 
 
1444
 
/**
1445
 
 * Compound filter semantics were orginially not implemented
1446
 
 * correctly.  Originally, each component filter f(i) is replaced by
1447
 
 * f'(i) = f(i) && g, where g is the filter for the compound
1448
 
 * transliterator.
1449
 
 * 
1450
 
 * From Mark:
1451
 
 *
1452
 
 * Suppose and I have a transliterator X. Internally X is
1453
 
 * "Greek-Latin; Latin-Cyrillic; Any-Lower". I use a filter [^A].
1454
 
 * 
1455
 
 * The compound should convert all greek characters (through latin) to
1456
 
 * cyrillic, then lowercase the result. The filter should say "don't
1457
 
 * touch 'A' in the original". But because an intermediate result
1458
 
 * happens to go through "A", the Greek Alpha gets hung up.
1459
 
 */
1460
 
void TransliteratorTest::TestCompoundFilter(void) {
1461
 
    UParseError parseError;
1462
 
    UErrorCode status = U_ZERO_ERROR;
1463
 
    Transliterator *t = Transliterator::createInstance
1464
 
        ("Greek-Latin; Latin-Greek; Lower", UTRANS_FORWARD, parseError, status);
1465
 
    if (t == 0) {
1466
 
        errln("FAIL: createInstance failed");
1467
 
        return;
1468
 
    }
1469
 
    t->adoptFilter(new UnicodeSet("[^A]", status));
1470
 
    if (U_FAILURE(status)) {
1471
 
        errln("FAIL: UnicodeSet ct failed");
1472
 
        delete t;
1473
 
        return;
1474
 
    }
1475
 
    
1476
 
    // Only the 'A' at index 1 should remain unchanged
1477
 
    expect(*t,
1478
 
           CharsToUnicodeString("BA\\u039A\\u0391"),
1479
 
           CharsToUnicodeString("\\u03b2A\\u03ba\\u03b1"));
1480
 
    delete t;
1481
 
}
1482
 
 
1483
 
void TransliteratorTest::TestRemove(void) {
1484
 
    UParseError parseError;
1485
 
    UErrorCode status = U_ZERO_ERROR;
1486
 
    Transliterator *t = Transliterator::createInstance("Remove[abc]", UTRANS_FORWARD, parseError, status);
1487
 
    if (t == 0) {
1488
 
        errln("FAIL: createInstance failed");
1489
 
        return;
1490
 
    }
1491
 
    
1492
 
    expect(*t, "Able bodied baker's cats", "Ale odied ker's ts");
1493
 
    delete t;
1494
 
}
1495
 
 
1496
 
void TransliteratorTest::TestToRules(void) {
1497
 
    const char* RBT = "rbt";
1498
 
    const char* SET = "set";
1499
 
    static const char* DATA[] = {
1500
 
        RBT,
1501
 
        "$a=\\u4E61; [$a] > A;",
1502
 
        "[\\u4E61] > A;",
1503
 
 
1504
 
        RBT,
1505
 
        "$white=[[:Zs:][:Zl:]]; $white{a} > A;",
1506
 
        "[[:Zs:][:Zl:]]{a} > A;",
1507
 
 
1508
 
        SET,
1509
 
        "[[:Zs:][:Zl:]]",
1510
 
        "[[:Zs:][:Zl:]]",
1511
 
 
1512
 
        SET,
1513
 
        "[:Ps:]",
1514
 
        "[:Ps:]",
1515
 
 
1516
 
        SET,
1517
 
        "[:L:]",
1518
 
        "[:L:]",
1519
 
 
1520
 
        SET,
1521
 
        "[[:L:]-[A]]",
1522
 
        "[[:L:]-[A]]",
1523
 
 
1524
 
        SET,
1525
 
        "[~[:Lu:][:Ll:]]",
1526
 
        "[~[:Lu:][:Ll:]]",
1527
 
 
1528
 
        SET,
1529
 
        "[~[a-z]]",
1530
 
        "[~[a-z]]",
1531
 
 
1532
 
        RBT,
1533
 
        "$white=[:Zs:]; $black=[^$white]; $black{a} > A;",
1534
 
        "[^[:Zs:]]{a} > A;",
1535
 
 
1536
 
        RBT,
1537
 
        "$a=[:Zs:]; $b=[[a-z]-$a]; $b{a} > A;",
1538
 
        "[[a-z]-[:Zs:]]{a} > A;",
1539
 
 
1540
 
        RBT,
1541
 
        "$a=[:Zs:]; $b=[$a&[a-z]]; $b{a} > A;",
1542
 
        "[[:Zs:]&[a-z]]{a} > A;",
1543
 
 
1544
 
        RBT,
1545
 
        "$a=[:Zs:]; $b=[x$a]; $b{a} > A;",
1546
 
        "[x[:Zs:]]{a} > A;",
1547
 
 
1548
 
        RBT,
1549
 
        "$accentMinus = [ [\\u0300-\\u0345] & [:M:] - [\\u0338]] ;"
1550
 
        "$macron = \\u0304 ;"
1551
 
        "$evowel = [aeiouyAEIOUY] ;"
1552
 
        "$iotasub = \\u0345 ;" 
1553
 
        "($evowel $macron $accentMinus *) i > | $1 $iotasub ;",
1554
 
        "([AEIOUYaeiouy]\\u0304[[\\u0300-\\u0345]&[:M:]-[\\u0338]]*)i > | $1 \\u0345;",
1555
 
 
1556
 
        RBT,
1557
 
        "([AEIOUYaeiouy]\\u0304[[:M:]-[\\u0304\\u0345]]*)i > | $1 \\u0345;",
1558
 
        "([AEIOUYaeiouy]\\u0304[[:M:]-[\\u0304\\u0345]]*)i > | $1 \\u0345;",
1559
 
    };
1560
 
    static const int32_t DATA_length = (int32_t)(sizeof(DATA) / sizeof(DATA[0]));
1561
 
 
1562
 
    for (int32_t d=0; d < DATA_length; d+=3) {
1563
 
        if (DATA[d] == RBT) {
1564
 
            // Transliterator test
1565
 
            UParseError parseError;
1566
 
            UErrorCode status = U_ZERO_ERROR;
1567
 
            Transliterator *t = Transliterator::createFromRules("ID",
1568
 
                                                                DATA[d+1], UTRANS_FORWARD, parseError, status);
1569
 
            if (t == 0) {
1570
 
                errln("FAIL: createFromRules failed");
1571
 
                return;
1572
 
            }
1573
 
            UnicodeString rules, escapedRules;
1574
 
            t->toRules(rules, FALSE);
1575
 
            t->toRules(escapedRules, TRUE);
1576
 
            UnicodeString expRules = CharsToUnicodeString(DATA[d+2]);
1577
 
            UnicodeString expEscapedRules(DATA[d+2]);
1578
 
            if (rules == expRules) {
1579
 
                logln((UnicodeString)"Ok: " + DATA[d+1] +
1580
 
                      " => " + rules);
1581
 
            } else {
1582
 
                errln((UnicodeString)"FAIL: " + DATA[d+1] +
1583
 
                      " => " + rules + ", exp " + expRules);
1584
 
            }
1585
 
            if (escapedRules == expEscapedRules) {
1586
 
                logln((UnicodeString)"Ok: " + DATA[d+1] +
1587
 
                      " => " + escapedRules);
1588
 
            } else {
1589
 
                errln((UnicodeString)"FAIL: " + DATA[d+1] +
1590
 
                      " => " + escapedRules + ", exp " + expEscapedRules);
1591
 
            }
1592
 
            delete t;
1593
 
            
1594
 
        } else {
1595
 
            // UnicodeSet test
1596
 
            UErrorCode status = U_ZERO_ERROR;
1597
 
            UnicodeString pat(DATA[d+1]);
1598
 
            UnicodeString expToPat(DATA[d+2]);
1599
 
            UnicodeSet set(pat, status);
1600
 
            if (U_FAILURE(status)) {
1601
 
                errln("FAIL: UnicodeSet ct failed");
1602
 
                return;
1603
 
            }
1604
 
            // Adjust spacing etc. as necessary.
1605
 
            UnicodeString toPat;
1606
 
            set.toPattern(toPat);
1607
 
            if (expToPat == toPat) {
1608
 
                logln((UnicodeString)"Ok: " + pat +
1609
 
                      " => " + toPat);
1610
 
            } else {
1611
 
                errln((UnicodeString)"FAIL: " + pat +
1612
 
                      " => " + prettify(toPat, TRUE) +
1613
 
                      ", exp " + prettify(pat, TRUE));
1614
 
            }
1615
 
        }
1616
 
    }
1617
 
}
1618
 
 
1619
 
void TransliteratorTest::TestContext() {
1620
 
    UTransPosition pos = {0, 2, 0, 1}; // cs cl s l
1621
 
    expect("de > x; {d}e > y;",
1622
 
           "de",
1623
 
           "ye",
1624
 
           &pos);
1625
 
 
1626
 
    expect("ab{c} > z;",
1627
 
           "xadabdabcy",
1628
 
           "xadabdabzy");
1629
 
}
1630
 
 
1631
 
void TransliteratorTest::TestSupplemental() { 
1632
 
 
1633
 
    expect(CharsToUnicodeString("$a=\\U00010300; $s=[\\U00010300-\\U00010323];"
1634
 
                                "a > $a; $s > i;"),
1635
 
           CharsToUnicodeString("ab\\U0001030Fx"),
1636
 
           CharsToUnicodeString("\\U00010300bix"));
1637
 
 
1638
 
    expect(CharsToUnicodeString("$a=[a-z\\U00010300-\\U00010323];"
1639
 
                                "$b=[A-Z\\U00010400-\\U0001044D];"
1640
 
                                "($a)($b) > $2 $1;"),
1641
 
           CharsToUnicodeString("aB\\U00010300\\U00010400c\\U00010401\\U00010301D"),
1642
 
           CharsToUnicodeString("Ba\\U00010400\\U00010300\\U00010401cD\\U00010301"));
1643
 
 
1644
 
    // k|ax\\U00010300xm
1645
 
 
1646
 
    // k|a\\U00010400\\U00010300xm
1647
 
    // ky|\\U00010400\\U00010300xm
1648
 
    // ky\\U00010400|\\U00010300xm
1649
 
 
1650
 
    // ky\\U00010400|\\U00010300\\U00010400m
1651
 
    // ky\\U00010400y|\\U00010400m
1652
 
    expect(CharsToUnicodeString("$a=[a\\U00010300-\\U00010323];"
1653
 
                                "$a {x} > | @ \\U00010400;"
1654
 
                                "{$a} [^\\u0000-\\uFFFF] > y;"),
1655
 
           CharsToUnicodeString("kax\\U00010300xm"),
1656
 
           CharsToUnicodeString("ky\\U00010400y\\U00010400m"));
1657
 
 
1658
 
    expectT("Any-Name",
1659
 
           CharsToUnicodeString("\\U00010330\\U000E0061\\u00A0"),
1660
 
           "{GOTHIC LETTER AHSA}{TAG LATIN SMALL LETTER A}{NO-BREAK SPACE}");
1661
 
 
1662
 
    expectT("Any-Hex/Unicode",
1663
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1664
 
           "U+10330U+10FF00U+E0061U+00A0");
1665
 
 
1666
 
    expectT("Any-Hex/C",
1667
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1668
 
           "\\U00010330\\U0010FF00\\U000E0061\\u00A0");
1669
 
 
1670
 
    expectT("Any-Hex/Perl",
1671
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1672
 
           "\\x{10330}\\x{10FF00}\\x{E0061}\\x{A0}");
1673
 
 
1674
 
    expectT("Any-Hex/Java",
1675
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1676
 
           "\\uD800\\uDF30\\uDBFF\\uDF00\\uDB40\\uDC61\\u00A0");
1677
 
 
1678
 
    expectT("Any-Hex/XML",
1679
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1680
 
           "&#x10330;&#x10FF00;&#xE0061;&#xA0;");
1681
 
 
1682
 
    expectT("Any-Hex/XML10",
1683
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1684
 
           "&#66352;&#1113856;&#917601;&#160;");
1685
 
 
1686
 
    expectT("[\\U000E0000-\\U000E0FFF] Remove",
1687
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\U000E0061\\u00A0"),
1688
 
           CharsToUnicodeString("\\U00010330\\U0010FF00\\u00A0"));
1689
 
}
1690
 
 
1691
 
void TransliteratorTest::TestQuantifier() { 
1692
 
 
1693
 
    // Make sure @ in a quantified anteContext works
1694
 
    expect("a+ {b} > | @@ c; A > a; (a+ c) > '(' $1 ')';",
1695
 
           "AAAAAb",
1696
 
           "aaa(aac)");
1697
 
 
1698
 
    // Make sure @ in a quantified postContext works
1699
 
    expect("{b} a+ > c @@ |; (a+) > '(' $1 ')';",
1700
 
           "baaaaa",
1701
 
           "caa(aaa)");
1702
 
 
1703
 
    // Make sure @ in a quantified postContext with seg ref works
1704
 
    expect("{(b)} a+ > $1 @@ |; (a+) > '(' $1 ')';",
1705
 
           "baaaaa",
1706
 
           "baa(aaa)");
1707
 
 
1708
 
    // Make sure @ past ante context doesn't enter ante context
1709
 
    UTransPosition pos = {0, 5, 3, 5};
1710
 
    expect("a+ {b} > | @@ c; x > y; (a+ c) > '(' $1 ')';",
1711
 
           "xxxab",
1712
 
           "xxx(ac)",
1713
 
           &pos);
1714
 
 
1715
 
    // Make sure @ past post context doesn't pass limit
1716
 
    UTransPosition pos2 = {0, 4, 0, 2};
1717
 
    expect("{b} a+ > c @@ |; x > y; a > A;",
1718
 
           "baxx",
1719
 
           "caxx",
1720
 
           &pos2);
1721
 
 
1722
 
    // Make sure @ past post context doesn't enter post context
1723
 
    expect("{b} a+ > c @@ |; x > y; a > A;",
1724
 
           "baxx",
1725
 
           "cayy");
1726
 
 
1727
 
    expect("(ab)? c > d;",
1728
 
           "c abc ababc",
1729
 
           "d d abd");
1730
 
    
1731
 
    // NOTE: The (ab)+ when referenced just yields a single "ab",
1732
 
    // not the full sequence of them.  This accords with perl behavior.
1733
 
    expect("(ab)+ {x} > '(' $1 ')';",
1734
 
           "x abx ababxy",
1735
 
           "x ab(ab) abab(ab)y");
1736
 
 
1737
 
    expect("b+ > x;",
1738
 
           "ac abc abbc abbbc",
1739
 
           "ac axc axc axc");
1740
 
 
1741
 
    expect("[abc]+ > x;",
1742
 
           "qac abrc abbcs abtbbc",
1743
 
           "qx xrx xs xtx");
1744
 
 
1745
 
    expect("q{(ab)+} > x;",
1746
 
           "qa qab qaba qababc qaba",
1747
 
           "qa qx qxa qxc qxa");
1748
 
 
1749
 
    expect("q(ab)* > x;",
1750
 
           "qa qab qaba qababc",
1751
 
           "xa x xa xc");
1752
 
 
1753
 
    // NOTE: The (ab)+ when referenced just yields a single "ab",
1754
 
    // not the full sequence of them.  This accords with perl behavior.
1755
 
    expect("q(ab)* > '(' $1 ')';",
1756
 
           "qa qab qaba qababc",
1757
 
           "()a (ab) (ab)a (ab)c");
1758
 
 
1759
 
    // 'foo'+ and 'foo'* -- the quantifier should apply to the entire
1760
 
    // quoted string
1761
 
    expect("'ab'+ > x;",
1762
 
           "bb ab ababb",
1763
 
           "bb x xb");
1764
 
 
1765
 
    // $foo+ and $foo* -- the quantifier should apply to the entire
1766
 
    // variable reference
1767
 
    expect("$var = ab; $var+ > x;",
1768
 
           "bb ab ababb",
1769
 
           "bb x xb");
1770
 
}
1771
 
 
1772
 
class TestTrans : public NullTransliterator {
1773
 
public:
1774
 
    TestTrans(const UnicodeString& id) {
1775
 
        setID(id);
1776
 
    }
1777
 
};
1778
 
 
1779
 
/**
1780
 
 * Test Source-Target/Variant.
1781
 
 */
1782
 
void TransliteratorTest::TestSTV(void) {
1783
 
    int32_t ns = Transliterator::countAvailableSources();
1784
 
    if (ns < 0 || ns > 255) {
1785
 
        errln((UnicodeString)"FAIL: Bad source count: " + ns);
1786
 
        return;
1787
 
    }
1788
 
    int32_t i;
1789
 
    for (i=0; i<ns; ++i) {
1790
 
        UnicodeString source;
1791
 
        Transliterator::getAvailableSource(i, source);
1792
 
        logln((UnicodeString)"" + i + ": " + source);
1793
 
        if (source.length() == 0) {
1794
 
            errln("FAIL: empty source");
1795
 
            continue;
1796
 
        }
1797
 
        int32_t nt = Transliterator::countAvailableTargets(source);
1798
 
        if (nt < 0 || nt > 255) {
1799
 
            errln((UnicodeString)"FAIL: Bad target count: " + nt);
1800
 
            continue;
1801
 
        }
1802
 
        for (int32_t j=0; j<nt; ++j) {
1803
 
            UnicodeString target;
1804
 
            Transliterator::getAvailableTarget(j, source, target);
1805
 
            logln((UnicodeString)" " + j + ": " + target);
1806
 
            if (target.length() == 0) {
1807
 
                errln("FAIL: empty target");
1808
 
                continue;
1809
 
            }
1810
 
            int32_t nv = Transliterator::countAvailableVariants(source, target);
1811
 
            if (nv < 0 || nv > 255) {
1812
 
                errln((UnicodeString)"FAIL: Bad variant count: " + nv);
1813
 
                continue;
1814
 
            }
1815
 
            for (int32_t k=0; k<nv; ++k) {
1816
 
                UnicodeString variant;
1817
 
                Transliterator::getAvailableVariant(k, source, target, variant);
1818
 
                if (variant.length() == 0) { 
1819
 
                    logln((UnicodeString)"  " + k + ": <empty>");
1820
 
                } else {
1821
 
                    logln((UnicodeString)"  " + k + ": " + variant);
1822
 
                }
1823
 
            }
1824
 
        }
1825
 
    }
1826
 
 
1827
 
    // Test registration
1828
 
    const char* IDS[] = { "Fieruwer", "Seoridf-Sweorie", "Oewoir-Oweri/Vsie" };
1829
 
    for (i=0; i<3; ++i) {
1830
 
        Transliterator *t = new TestTrans(IDS[i]);
1831
 
        if (t == 0) {
1832
 
            errln("FAIL: out of memory");
1833
 
            return;
1834
 
        }
1835
 
        if (t->getID() != IDS[i]) {
1836
 
            errln((UnicodeString)"FAIL: ID mismatch for " + IDS[i]);
1837
 
            delete t;
1838
 
            return;
1839
 
        }
1840
 
        Transliterator::registerInstance(t);
1841
 
        UErrorCode status = U_ZERO_ERROR;
1842
 
        t = Transliterator::createInstance(IDS[i], UTRANS_FORWARD, status);
1843
 
        if (t == NULL) {
1844
 
            errln((UnicodeString)"FAIL: Registration/creation failed for ID " +
1845
 
                  IDS[i]);
1846
 
        } else {
1847
 
            logln((UnicodeString)"Ok: Registration/creation succeeded for ID " +
1848
 
                  IDS[i]);
1849
 
            delete t;
1850
 
        }
1851
 
        Transliterator::unregister(IDS[i]);
1852
 
        t = Transliterator::createInstance(IDS[i], UTRANS_FORWARD, status);
1853
 
        if (t != NULL) {
1854
 
            errln((UnicodeString)"FAIL: Unregistration failed for ID " +
1855
 
                  IDS[i]);
1856
 
            delete t;
1857
 
        }
1858
 
    }
1859
 
}
1860
 
 
1861
 
/**
1862
 
 * Test inverse of Greek-Latin; Title()
1863
 
 */
1864
 
void TransliteratorTest::TestCompoundInverse(void) {
1865
 
    UParseError parseError;
1866
 
    UErrorCode status = U_ZERO_ERROR;
1867
 
    Transliterator *t = Transliterator::createInstance
1868
 
        ("Greek-Latin; Title()", UTRANS_REVERSE,parseError, status);
1869
 
    if (t == 0) {
1870
 
        errln("FAIL: createInstance");
1871
 
        return;
1872
 
    }
1873
 
    UnicodeString exp("(Title);Latin-Greek");
1874
 
    if (t->getID() == exp) {
1875
 
        logln("Ok: inverse of \"Greek-Latin; Title()\" is \"" +
1876
 
              t->getID());
1877
 
    } else {
1878
 
        errln("FAIL: inverse of \"Greek-Latin; Title()\" is \"" +
1879
 
              t->getID() + "\", expected \"" + exp + "\"");
1880
 
    }
1881
 
    delete t;
1882
 
}
1883
 
 
1884
 
/**
1885
 
 * Test NFD chaining with RBT
1886
 
 */
1887
 
void TransliteratorTest::TestNFDChainRBT() {
1888
 
    UParseError pe;
1889
 
    UErrorCode ec = U_ZERO_ERROR;
1890
 
    Transliterator* t = Transliterator::createFromRules(
1891
 
                               "TEST", "::NFD; aa > Q; a > q;",
1892
 
                               UTRANS_FORWARD, pe, ec);
1893
 
    if (t == NULL || U_FAILURE(ec)) {
1894
 
        errln("FAIL: Transliterator::createFromRules failed with %s", u_errorName(ec));
1895
 
        return;
1896
 
    }
1897
 
    expect(*t, "aa", "Q");
1898
 
    delete t;
1899
 
 
1900
 
    // TEMPORARY TESTS -- BEING DEBUGGED
1901
 
//=-    UnicodeString s, s2;
1902
 
//=-    t = Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, pe, ec);
1903
 
//=-    s = CharsToUnicodeString("rmk\\u1E63\\u0113t");
1904
 
//=-    s2 = CharsToUnicodeString("\\u0930\\u094D\\u092E\\u094D\\u0915\\u094D\\u0937\\u0947\\u0924\\u094D");
1905
 
//=-    expect(*t, s, s2);
1906
 
//=-    delete t;
1907
 
//=-
1908
 
//=-    t = Transliterator::createInstance("Devanagari-Latin", UTRANS_FORWARD, pe, ec);
1909
 
//=-    expect(*t, s2, s);
1910
 
//=-    delete t;
1911
 
//=-
1912
 
//=-    t = Transliterator::createInstance("Latin-Devanagari;Devanagari-Latin", UTRANS_FORWARD, pe, ec);
1913
 
//=-    s = CharsToUnicodeString("rmk\\u1E63\\u0113t");
1914
 
//=-    expect(*t, s, s);
1915
 
//=-    delete t;
1916
 
 
1917
 
//    const char* source[] = {
1918
 
//        /*
1919
 
//        "\\u015Br\\u012Bmad",
1920
 
//        "bhagavadg\\u012Bt\\u0101",
1921
 
//        "adhy\\u0101ya",
1922
 
//        "arjuna",
1923
 
//        "vi\\u1E63\\u0101da",
1924
 
//        "y\\u014Dga",
1925
 
//        "dhr\\u0325tar\\u0101\\u1E63\\u1E6Dra",
1926
 
//        "uv\\u0101cr\\u0325",
1927
 
//        */
1928
 
//        "rmk\\u1E63\\u0113t",
1929
 
//      //"dharmak\\u1E63\\u0113tr\\u0113",
1930
 
//        /*
1931
 
//        "kuruk\\u1E63\\u0113tr\\u0113",
1932
 
//        "samav\\u0113t\\u0101",
1933
 
//        "yuyutsava-\\u1E25",
1934
 
//        "m\\u0101mak\\u0101-\\u1E25",
1935
 
//     // "p\\u0101\\u1E47\\u1E0Dav\\u0101\\u015Bcaiva",
1936
 
//        "kimakurvata",
1937
 
//        "san\\u0304java",
1938
 
//        */
1939
 
//
1940
 
//        0
1941
 
//    };
1942
 
//    const char* expected[] = {
1943
 
//        /*
1944
 
//        "\\u0936\\u094d\\u0930\\u0940\\u092e\\u0926\\u094d",
1945
 
//        "\\u092d\\u0917\\u0935\\u0926\\u094d\\u0917\\u0940\\u0924\\u093e",
1946
 
//        "\\u0905\\u0927\\u094d\\u092f\\u093e\\u092f",
1947
 
//        "\\u0905\\u0930\\u094d\\u091c\\u0941\\u0928",
1948
 
//        "\\u0935\\u093f\\u0937\\u093e\\u0926",
1949
 
//        "\\u092f\\u094b\\u0917",
1950
 
//        "\\u0927\\u0943\\u0924\\u0930\\u093e\\u0937\\u094d\\u091f\\u094d\\u0930",
1951
 
//        "\\u0909\\u0935\\u093E\\u091A\\u0943",
1952
 
//        */
1953
 
//        "\\u0927",
1954
 
//        //"\\u0927\\u0930\\u094d\\u092e\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
1955
 
//        /*
1956
 
//        "\\u0915\\u0941\\u0930\\u0941\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
1957
 
//        "\\u0938\\u092e\\u0935\\u0947\\u0924\\u093e",
1958
 
//        "\\u092f\\u0941\\u092f\\u0941\\u0924\\u094d\\u0938\\u0935\\u0903",
1959
 
//        "\\u092e\\u093e\\u092e\\u0915\\u093e\\u0903",
1960
 
//    //  "\\u092a\\u093e\\u0923\\u094d\\u0921\\u0935\\u093e\\u0936\\u094d\\u091a\\u0948\\u0935",
1961
 
//        "\\u0915\\u093f\\u092e\\u0915\\u0941\\u0930\\u094d\\u0935\\u0924",
1962
 
//        "\\u0938\\u0902\\u091c\\u0935",
1963
 
//        */
1964
 
//        0
1965
 
//    };
1966
 
//    UErrorCode status = U_ZERO_ERROR;
1967
 
//    UParseError parseError;
1968
 
//    UnicodeString message;
1969
 
//    Transliterator* latinToDevToLatin=Transliterator::createInstance("Latin-Devanagari;Devanagari-Latin", UTRANS_FORWARD, parseError, status);
1970
 
//    Transliterator* devToLatinToDev=Transliterator::createInstance("Devanagari-Latin;Latin-Devanagari", UTRANS_FORWARD, parseError, status);
1971
 
//    if(U_FAILURE(status)){
1972
 
//        errln("FAIL: construction " +   UnicodeString(" Error: ") + u_errorName(status));
1973
 
//        errln("PreContext: " + prettify(parseError.preContext) + "PostContext: " + prettify( parseError.postContext) );
1974
 
//        delete latinToDevToLatin;
1975
 
//        delete devToLatinToDev;
1976
 
//        return;
1977
 
//    }
1978
 
//    UnicodeString gotResult;
1979
 
//    for(int i= 0; source[i] != 0; i++){
1980
 
//        gotResult = source[i];
1981
 
//        expect(*latinToDevToLatin,CharsToUnicodeString(source[i]),CharsToUnicodeString(source[i]));
1982
 
//        expect(*devToLatinToDev,CharsToUnicodeString(expected[i]),CharsToUnicodeString(expected[i]));
1983
 
//    }
1984
 
//    delete latinToDevToLatin;
1985
 
//    delete devToLatinToDev;
1986
 
}
1987
 
 
1988
 
/**
1989
 
 * Inverse of "Null" should be "Null". (J21)
1990
 
 */
1991
 
void TransliteratorTest::TestNullInverse() {
1992
 
    UParseError pe;
1993
 
    UErrorCode ec = U_ZERO_ERROR;
1994
 
    Transliterator *t = Transliterator::createInstance("Null", UTRANS_FORWARD, pe, ec);
1995
 
    if (t == 0 || U_FAILURE(ec)) {
1996
 
        errln("FAIL: createInstance");
1997
 
        return;
1998
 
    }
1999
 
    Transliterator *u = t->createInverse(ec);
2000
 
    if (u == 0 || U_FAILURE(ec)) {
2001
 
        errln("FAIL: createInverse");
2002
 
        delete t;
2003
 
        return;
2004
 
    }
2005
 
    if (u->getID() != "Null") {
2006
 
        errln("FAIL: Inverse of Null should be Null");
2007
 
    }
2008
 
    delete t;
2009
 
    delete u;
2010
 
}
2011
 
 
2012
 
/**
2013
 
 * Check ID of inverse of alias. (J22)
2014
 
 */
2015
 
void TransliteratorTest::TestAliasInverseID() {
2016
 
    UnicodeString ID("Latin-Hangul", ""); // This should be any alias ID with an inverse
2017
 
    UParseError pe;
2018
 
    UErrorCode ec = U_ZERO_ERROR;
2019
 
    Transliterator *t = Transliterator::createInstance(ID, UTRANS_FORWARD, pe, ec);
2020
 
    if (t == 0 || U_FAILURE(ec)) {
2021
 
        errln("FAIL: createInstance");
2022
 
        return;
2023
 
    }
2024
 
    Transliterator *u = t->createInverse(ec);
2025
 
    if (u == 0 || U_FAILURE(ec)) {
2026
 
        errln("FAIL: createInverse");
2027
 
        delete t;
2028
 
        return;
2029
 
    }
2030
 
    UnicodeString exp = "Hangul-Latin";
2031
 
    UnicodeString got = u->getID();
2032
 
    if (got != exp) {
2033
 
        errln((UnicodeString)"FAIL: Inverse of " + ID + " is " + got +
2034
 
              ", expected " + exp);
2035
 
    }
2036
 
    delete t;
2037
 
    delete u;
2038
 
}
2039
 
 
2040
 
/**
2041
 
 * Test IDs of inverses of compound transliterators. (J20)
2042
 
 */
2043
 
void TransliteratorTest::TestCompoundInverseID() {
2044
 
    UnicodeString ID = "Latin-Jamo;NFC(NFD)";
2045
 
    UParseError pe;
2046
 
    UErrorCode ec = U_ZERO_ERROR;
2047
 
    Transliterator *t = Transliterator::createInstance(ID, UTRANS_FORWARD, pe, ec);
2048
 
    if (t == 0 || U_FAILURE(ec)) {
2049
 
        errln("FAIL: createInstance");
2050
 
        return;
2051
 
    }
2052
 
    Transliterator *u = t->createInverse(ec);
2053
 
    if (u == 0 || U_FAILURE(ec)) {
2054
 
        errln("FAIL: createInverse");
2055
 
        delete t;
2056
 
        return;
2057
 
    }
2058
 
    UnicodeString exp = "NFD(NFC);Jamo-Latin";
2059
 
    UnicodeString got = u->getID();
2060
 
    if (got != exp) {
2061
 
        errln((UnicodeString)"FAIL: Inverse of " + ID + " is " + got +
2062
 
              ", expected " + exp);
2063
 
    }
2064
 
    delete t;
2065
 
    delete u;
2066
 
}
2067
 
 
2068
 
/**
2069
 
 * Test undefined variable.
2070
 
 
2071
 
 */
2072
 
void TransliteratorTest::TestUndefinedVariable() {
2073
 
    UnicodeString rule = "$initial } a <> \\u1161;";
2074
 
    UParseError pe;
2075
 
    UErrorCode ec = U_ZERO_ERROR;
2076
 
    Transliterator *t = new RuleBasedTransliterator("<ID>", rule, UTRANS_FORWARD, 0, pe, ec);
2077
 
    delete t;
2078
 
    if (U_FAILURE(ec)) {
2079
 
        logln((UnicodeString)"OK: Got exception for " + rule + ", as expected: " +
2080
 
              u_errorName(ec));
2081
 
        return;
2082
 
    }
2083
 
    errln((UnicodeString)"Fail: bogus rule " + rule + " compiled with error " +
2084
 
          u_errorName(ec));
2085
 
}
2086
 
 
2087
 
/**
2088
 
 * Test empty context.
2089
 
 */
2090
 
void TransliteratorTest::TestEmptyContext() {
2091
 
    expect(" { a } > b;", "xay a ", "xby b ");
2092
 
}
2093
 
 
2094
 
/**
2095
 
* Test compound filter ID syntax
2096
 
*/
2097
 
void TransliteratorTest::TestCompoundFilterID(void) {
2098
 
    static const char* DATA[] = {
2099
 
        // Col. 1 = ID or rule set (latter must start with #)
2100
 
 
2101
 
        // = columns > 1 are null if expect col. 1 to be illegal =
2102
 
 
2103
 
        // Col. 2 = direction, "F..." or "R..."
2104
 
        // Col. 3 = source string
2105
 
        // Col. 4 = exp result
2106
 
 
2107
 
        "[abc]; [abc]", NULL, NULL, NULL, // multiple filters
2108
 
        "Latin-Greek; [abc];", NULL, NULL, NULL, // misplaced filter
2109
 
        "[b]; Latin-Greek; Upper; ([xyz])", "F", "abc", "a\\u0392c",
2110
 
        "[b]; (Lower); Latin-Greek; Upper(); ([\\u0392])", "R", "\\u0391\\u0392\\u0393", "\\u0391b\\u0393",
2111
 
        "#\n::[b]; ::Latin-Greek; ::Upper; ::([xyz]);", "F", "abc", "a\\u0392c",
2112
 
        "#\n::[b]; ::(Lower); ::Latin-Greek; ::Upper(); ::([\\u0392]);", "R", "\\u0391\\u0392\\u0393", "\\u0391b\\u0393",
2113
 
        NULL,
2114
 
    };
2115
 
 
2116
 
    for (int32_t i=0; DATA[i]; i+=4) {
2117
 
        UnicodeString id = CharsToUnicodeString(DATA[i]);
2118
 
        UTransDirection direction = (DATA[i+1] != NULL && DATA[i+1][0] == 'R') ?
2119
 
            UTRANS_REVERSE : UTRANS_FORWARD;
2120
 
        UnicodeString source;
2121
 
        UnicodeString exp;
2122
 
        if (DATA[i+2] != NULL) {
2123
 
            source = CharsToUnicodeString(DATA[i+2]);
2124
 
            exp = CharsToUnicodeString(DATA[i+3]);
2125
 
        }
2126
 
        UBool expOk = (DATA[i+1] != NULL);
2127
 
        Transliterator* t = NULL;
2128
 
        UParseError pe;
2129
 
        UErrorCode ec = U_ZERO_ERROR;
2130
 
        if (id.charAt(0) == 0x23/*#*/) {
2131
 
            t = Transliterator::createFromRules("ID", id, direction, pe, ec);
2132
 
        } else {
2133
 
            t = Transliterator::createInstance(id, direction, pe, ec);
2134
 
        }
2135
 
        UBool ok = (t != NULL && U_SUCCESS(ec));
2136
 
        if (ok == expOk) {
2137
 
            logln((UnicodeString)"Ok: " + id + " => " + (t!=0?t->getID():(UnicodeString)"NULL") + ", " +
2138
 
                  u_errorName(ec));
2139
 
            if (source.length() != 0) {
2140
 
                expect(*t, source, exp);
2141
 
            }
2142
 
            delete t;
2143
 
        } else {
2144
 
            errln((UnicodeString)"FAIL: " + id + " => " + (t!=0?t->getID():(UnicodeString)"NULL") + ", " +
2145
 
                  u_errorName(ec));
2146
 
        }
2147
 
    }
2148
 
}
2149
 
 
2150
 
/**
2151
 
 * Test new property set syntax
2152
 
 */
2153
 
void TransliteratorTest::TestPropertySet() {
2154
 
    expect("a>A; \\p{Lu}>x; \\p{ANY}>y;", "abcDEF", "Ayyxxx");
2155
 
    expect("(.+)>'[' $1 ']';", " a stitch \n in time \r saves 9",
2156
 
           "[ a stitch ]\n[ in time ]\r[ saves 9]");
2157
 
}
2158
 
 
2159
 
/**
2160
 
 * Test various failure points of the new 2.0 engine.
2161
 
 */
2162
 
void TransliteratorTest::TestNewEngine() {
2163
 
    UParseError pe;
2164
 
    UErrorCode ec = U_ZERO_ERROR;
2165
 
    Transliterator *t = Transliterator::createInstance("Latin-Hiragana", UTRANS_FORWARD, pe, ec);
2166
 
    if (t == 0 || U_FAILURE(ec)) {
2167
 
        errln("FAIL: createInstance Latin-Hiragana");
2168
 
        return;
2169
 
    }
2170
 
    // Katakana should be untouched
2171
 
    expect(*t, CharsToUnicodeString("a\\u3042\\u30A2"),
2172
 
           CharsToUnicodeString("\\u3042\\u3042\\u30A2"));
2173
 
 
2174
 
    delete t;
2175
 
 
2176
 
#if 1
2177
 
    // This test will only work if Transliterator.ROLLBACK is
2178
 
    // true.  Otherwise, this test will fail, revealing a
2179
 
    // limitation of global filters in incremental mode.
2180
 
    Transliterator *a =
2181
 
        Transliterator::createFromRules("a", "a > A;", UTRANS_FORWARD, pe, ec);
2182
 
    Transliterator *A =
2183
 
        Transliterator::createFromRules("A", "A > b;", UTRANS_FORWARD, pe, ec);
2184
 
    if (U_FAILURE(ec)) {
2185
 
        delete a;
2186
 
        delete A;
2187
 
        return;
2188
 
    }
2189
 
 
2190
 
    Transliterator* array[3];
2191
 
    array[0] = a;
2192
 
    array[1] = Transliterator::createInstance("NFD", UTRANS_FORWARD, pe, ec);
2193
 
    array[2] = A;
2194
 
    if (U_FAILURE(ec)) {
2195
 
        errln("FAIL: createInstance NFD");
2196
 
        delete a;
2197
 
        delete A;
2198
 
        delete array[1];
2199
 
        return;
2200
 
    }
2201
 
 
2202
 
    t = new CompoundTransliterator(array, 3, new UnicodeSet("[:Ll:]", ec));
2203
 
    if (U_FAILURE(ec)) {
2204
 
        errln("FAIL: UnicodeSet constructor");
2205
 
        delete a;
2206
 
        delete A;
2207
 
        delete array[1];
2208
 
        delete t;
2209
 
        return;
2210
 
    }
2211
 
 
2212
 
    expect(*t, "aAaA", "bAbA");
2213
 
    delete a;
2214
 
    delete A;
2215
 
    delete array[1];
2216
 
    delete t;
2217
 
#endif
2218
 
 
2219
 
    expect("$smooth = x; $macron = q; [:^L:] { ([aeiouyAEIOUY] $macron?) } [^aeiouyAEIOUY$smooth$macron] > | $1 $smooth ;",
2220
 
           "a",
2221
 
           "ax");
2222
 
 
2223
 
    UnicodeString gr = CharsToUnicodeString(
2224
 
        "$ddot = \\u0308 ;"
2225
 
        "$lcgvowel = [\\u03b1\\u03b5\\u03b7\\u03b9\\u03bf\\u03c5\\u03c9] ;"
2226
 
        "$rough = \\u0314 ;"
2227
 
        "($lcgvowel+ $ddot?) $rough > h | $1 ;"
2228
 
        "\\u03b1 <> a ;"
2229
 
        "$rough <> h ;");
2230
 
 
2231
 
    expect(gr, CharsToUnicodeString("\\u03B1\\u0314"), "ha");
2232
 
}
2233
 
 
2234
 
/**
2235
 
 * Test quantified segment behavior.  We want:
2236
 
 * ([abc])+ > x $1 x; applied to "cba" produces "xax"
2237
 
 */
2238
 
void TransliteratorTest::TestQuantifiedSegment(void) {
2239
 
    // The normal case
2240
 
    expect("([abc]+) > x $1 x;", "cba", "xcbax");
2241
 
 
2242
 
    // The tricky case; the quantifier is around the segment
2243
 
    expect("([abc])+ > x $1 x;", "cba", "xax");
2244
 
 
2245
 
    // Tricky case in reverse direction
2246
 
    expect("([abc])+ { q > x $1 x;", "cbaq", "cbaxax");
2247
 
 
2248
 
    // Check post-context segment
2249
 
    expect("{q} ([a-d])+ > '(' $1 ')';", "ddqcba", "dd(a)cba");
2250
 
 
2251
 
    // Test toRule/toPattern for non-quantified segment.
2252
 
    // Careful with spacing here.
2253
 
    UnicodeString r("([a-c]){q} > x $1 x;");
2254
 
    UParseError pe;
2255
 
    UErrorCode ec = U_ZERO_ERROR;
2256
 
    Transliterator* t = Transliterator::createFromRules("ID", r, UTRANS_FORWARD, pe, ec);
2257
 
    if (U_FAILURE(ec)) {
2258
 
        errln("FAIL: createFromRules");
2259
 
        delete t;
2260
 
        return;
2261
 
    }
2262
 
    UnicodeString rr;
2263
 
    t->toRules(rr, TRUE);
2264
 
    if (r != rr) {
2265
 
        errln((UnicodeString)"FAIL: \"" + r + "\" x toRules() => \"" + rr + "\"");
2266
 
    } else {
2267
 
        logln((UnicodeString)"Ok: \"" + r + "\" x toRules() => \"" + rr + "\"");
2268
 
    }
2269
 
    delete t;
2270
 
 
2271
 
    // Test toRule/toPattern for quantified segment.
2272
 
    // Careful with spacing here.
2273
 
    r = "([a-c])+{q} > x $1 x;";
2274
 
    t = Transliterator::createFromRules("ID", r, UTRANS_FORWARD, pe, ec);
2275
 
    if (U_FAILURE(ec)) {
2276
 
        errln("FAIL: createFromRules");
2277
 
        delete t;
2278
 
        return;
2279
 
    }
2280
 
    t->toRules(rr, TRUE);
2281
 
    if (r != rr) {
2282
 
        errln((UnicodeString)"FAIL: \"" + r + "\" x toRules() => \"" + rr + "\"");
2283
 
    } else {
2284
 
        logln((UnicodeString)"Ok: \"" + r + "\" x toRules() => \"" + rr + "\"");
2285
 
    }
2286
 
    delete t;
2287
 
}
2288
 
 
2289
 
//======================================================================
2290
 
// Ram's tests
2291
 
//======================================================================
2292
 
void TransliteratorTest::TestDevanagariLatinRT(){
2293
 
    const int MAX_LEN= 52;
2294
 
    const char* const source[MAX_LEN] = {
2295
 
        "bh\\u0101rata",
2296
 
        "kra",
2297
 
        "k\\u1E63a",
2298
 
        "khra",
2299
 
        "gra",
2300
 
        "\\u1E45ra",
2301
 
        "cra",
2302
 
        "chra",
2303
 
        "j\\u00F1a",
2304
 
        "jhra",
2305
 
        "\\u00F1ra",
2306
 
        "\\u1E6Dya",
2307
 
        "\\u1E6Dhra",
2308
 
        "\\u1E0Dya",
2309
 
      //"r\\u0323ya", // \u095c is not valid in Devanagari
2310
 
        "\\u1E0Dhya",
2311
 
        "\\u1E5Bhra",
2312
 
        "\\u1E47ra",
2313
 
        "tta",
2314
 
        "thra",
2315
 
        "dda",
2316
 
        "dhra",
2317
 
        "nna",
2318
 
        "pra",
2319
 
        "phra",
2320
 
        "bra",
2321
 
        "bhra",
2322
 
        "mra",
2323
 
        "\\u1E49ra",
2324
 
      //"l\\u0331ra",
2325
 
        "yra",
2326
 
        "\\u1E8Fra",
2327
 
      //"l-",
2328
 
        "vra",
2329
 
        "\\u015Bra",
2330
 
        "\\u1E63ra",
2331
 
        "sra",
2332
 
        "hma",
2333
 
        "\\u1E6D\\u1E6Da",
2334
 
        "\\u1E6D\\u1E6Dha",
2335
 
        "\\u1E6Dh\\u1E6Dha",
2336
 
        "\\u1E0D\\u1E0Da",
2337
 
        "\\u1E0D\\u1E0Dha",
2338
 
        "\\u1E6Dya",
2339
 
        "\\u1E6Dhya",
2340
 
        "\\u1E0Dya",
2341
 
        "\\u1E0Dhya",
2342
 
        // Not roundtrippable -- 
2343
 
        // \\u0939\\u094d\\u094d\\u092E  - hma
2344
 
        // \\u0939\\u094d\\u092E         - hma
2345
 
        // CharsToUnicodeString("hma"),
2346
 
        "hya",
2347
 
        "\\u015Br\\u0325",
2348
 
        "\\u015Bca",
2349
 
        "\\u0115",
2350
 
        "san\\u0304j\\u012Bb s\\u0113nagupta",
2351
 
        "\\u0101nand vaddir\\u0101ju",    
2352
 
        "\\u0101",
2353
 
        "a"
2354
 
    };
2355
 
    const char* const expected[MAX_LEN] = {
2356
 
        "\\u092D\\u093E\\u0930\\u0924",   /* bha\\u0304rata */
2357
 
        "\\u0915\\u094D\\u0930",          /* kra         */
2358
 
        "\\u0915\\u094D\\u0937",          /* ks\\u0323a  */
2359
 
        "\\u0916\\u094D\\u0930",          /* khra        */
2360
 
        "\\u0917\\u094D\\u0930",          /* gra         */
2361
 
        "\\u0919\\u094D\\u0930",          /* n\\u0307ra  */
2362
 
        "\\u091A\\u094D\\u0930",          /* cra         */
2363
 
        "\\u091B\\u094D\\u0930",          /* chra        */
2364
 
        "\\u091C\\u094D\\u091E",          /* jn\\u0303a  */
2365
 
        "\\u091D\\u094D\\u0930",          /* jhra        */
2366
 
        "\\u091E\\u094D\\u0930",          /* n\\u0303ra  */
2367
 
        "\\u091F\\u094D\\u092F",          /* t\\u0323ya  */
2368
 
        "\\u0920\\u094D\\u0930",          /* t\\u0323hra */
2369
 
        "\\u0921\\u094D\\u092F",          /* d\\u0323ya  */
2370
 
      //"\\u095C\\u094D\\u092F",        /* r\\u0323ya  */ // \u095c is not valid in Devanagari
2371
 
        "\\u0922\\u094D\\u092F",          /* d\\u0323hya */
2372
 
        "\\u0922\\u093C\\u094D\\u0930",   /* r\\u0323hra */
2373
 
        "\\u0923\\u094D\\u0930",          /* n\\u0323ra  */
2374
 
        "\\u0924\\u094D\\u0924",          /* tta         */
2375
 
        "\\u0925\\u094D\\u0930",          /* thra        */
2376
 
        "\\u0926\\u094D\\u0926",          /* dda         */
2377
 
        "\\u0927\\u094D\\u0930",          /* dhra        */
2378
 
        "\\u0928\\u094D\\u0928",          /* nna         */
2379
 
        "\\u092A\\u094D\\u0930",          /* pra         */
2380
 
        "\\u092B\\u094D\\u0930",          /* phra        */
2381
 
        "\\u092C\\u094D\\u0930",          /* bra         */
2382
 
        "\\u092D\\u094D\\u0930",          /* bhra        */
2383
 
        "\\u092E\\u094D\\u0930",          /* mra         */
2384
 
        "\\u0929\\u094D\\u0930",          /* n\\u0331ra  */
2385
 
      //"\\u0934\\u094D\\u0930",        /* l\\u0331ra  */
2386
 
        "\\u092F\\u094D\\u0930",          /* yra         */
2387
 
        "\\u092F\\u093C\\u094D\\u0930",   /* y\\u0307ra  */
2388
 
      //"l-",
2389
 
        "\\u0935\\u094D\\u0930",          /* vra         */
2390
 
        "\\u0936\\u094D\\u0930",          /* s\\u0301ra  */
2391
 
        "\\u0937\\u094D\\u0930",          /* s\\u0323ra  */
2392
 
        "\\u0938\\u094D\\u0930",          /* sra         */
2393
 
        "\\u0939\\u094d\\u092E",          /* hma         */
2394
 
        "\\u091F\\u094D\\u091F",          /* t\\u0323t\\u0323a  */
2395
 
        "\\u091F\\u094D\\u0920",          /* t\\u0323t\\u0323ha */
2396
 
        "\\u0920\\u094D\\u0920",          /* t\\u0323ht\\u0323ha*/
2397
 
        "\\u0921\\u094D\\u0921",          /* d\\u0323d\\u0323a  */
2398
 
        "\\u0921\\u094D\\u0922",          /* d\\u0323d\\u0323ha */
2399
 
        "\\u091F\\u094D\\u092F",          /* t\\u0323ya  */
2400
 
        "\\u0920\\u094D\\u092F",          /* t\\u0323hya */
2401
 
        "\\u0921\\u094D\\u092F",          /* d\\u0323ya  */
2402
 
        "\\u0922\\u094D\\u092F",          /* d\\u0323hya */
2403
 
     // "hma",                         /* hma         */
2404
 
        "\\u0939\\u094D\\u092F",          /* hya         */
2405
 
        "\\u0936\\u0943",                 /* s\\u0301r\\u0325a  */
2406
 
        "\\u0936\\u094D\\u091A",          /* s\\u0301ca  */
2407
 
        "\\u090d",                        /* e\\u0306    */
2408
 
        "\\u0938\\u0902\\u091C\\u0940\\u092C\\u094D \\u0938\\u0947\\u0928\\u0917\\u0941\\u092A\\u094D\\u0924",
2409
 
        "\\u0906\\u0928\\u0902\\u0926\\u094D \\u0935\\u0926\\u094D\\u0926\\u093F\\u0930\\u093E\\u091C\\u0941",    
2410
 
        "\\u0906",
2411
 
        "\\u0905",
2412
 
    };
2413
 
    UErrorCode status = U_ZERO_ERROR;
2414
 
    UParseError parseError;
2415
 
    UnicodeString message;
2416
 
    Transliterator* latinToDev=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
2417
 
    Transliterator* devToLatin=Transliterator::createInstance("Devanagari-Latin", UTRANS_FORWARD, parseError, status);
2418
 
    if(U_FAILURE(status)){
2419
 
        errln("FAIL: construction " +   UnicodeString(" Error: ") + u_errorName(status));
2420
 
        errln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
2421
 
        return;
2422
 
    }
2423
 
    UnicodeString gotResult;
2424
 
    for(int i= 0; i<MAX_LEN; i++){
2425
 
        gotResult = source[i];
2426
 
        expect(*latinToDev,CharsToUnicodeString(source[i]),CharsToUnicodeString(expected[i]));
2427
 
        expect(*devToLatin,CharsToUnicodeString(expected[i]),CharsToUnicodeString(source[i]));
2428
 
    }
2429
 
    delete latinToDev;
2430
 
    delete devToLatin;
2431
 
}
2432
 
 
2433
 
void TransliteratorTest::TestTeluguLatinRT(){
2434
 
    const int MAX_LEN=10;
2435
 
    const char* const source[MAX_LEN] = {   
2436
 
        "raghur\\u0101m vi\\u015Bvan\\u0101dha",                         /* Raghuram Viswanadha    */
2437
 
        "\\u0101nand vaddir\\u0101ju",                                   /* Anand Vaddiraju        */
2438
 
        "r\\u0101j\\u012Bv ka\\u015Barab\\u0101da",                      /* Rajeev Kasarabada      */
2439
 
        "san\\u0304j\\u012Bv ka\\u015Barab\\u0101da",                    /* sanjeev kasarabada     */
2440
 
        "san\\u0304j\\u012Bb sen'gupta",                                 /* sanjib sengupata       */
2441
 
        "amar\\u0113ndra hanum\\u0101nula",                              /* Amarendra hanumanula   */
2442
 
        "ravi kum\\u0101r vi\\u015Bvan\\u0101dha",                       /* Ravi Kumar Viswanadha  */
2443
 
        "\\u0101ditya kandr\\u0113gula",                                 /* Aditya Kandregula      */
2444
 
        "\\u015Br\\u012Bdhar ka\\u1E47\\u1E6Dama\\u015Be\\u1E6D\\u1E6Di",/* Shridhar Kantamsetty   */
2445
 
        "m\\u0101dhav de\\u015Be\\u1E6D\\u1E6Di"                         /* Madhav Desetty         */
2446
 
    };
2447
 
 
2448
 
    const char* const expected[MAX_LEN] = {
2449
 
        "\\u0c30\\u0c18\\u0c41\\u0c30\\u0c3e\\u0c2e\\u0c4d \\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27",     
2450
 
        "\\u0c06\\u0c28\\u0c02\\u0c26\\u0c4d \\u0C35\\u0C26\\u0C4D\\u0C26\\u0C3F\\u0C30\\u0C3E\\u0C1C\\u0C41",     
2451
 
        "\\u0c30\\u0c3e\\u0c1c\\u0c40\\u0c35\\u0c4d \\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26",
2452
 
        "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c35\\u0c4d \\u0c15\\u0c36\\u0c30\\u0c2c\\u0c3e\\u0c26",
2453
 
        "\\u0c38\\u0c02\\u0c1c\\u0c40\\u0c2c\\u0c4d \\u0c38\\u0c46\\u0c28\\u0c4d\\u0c17\\u0c41\\u0c2a\\u0c4d\\u0c24",
2454
 
        "\\u0c05\\u0c2e\\u0c30\\u0c47\\u0c02\\u0c26\\u0c4d\\u0c30 \\u0c39\\u0c28\\u0c41\\u0c2e\\u0c3e\\u0c28\\u0c41\\u0c32",
2455
 
        "\\u0c30\\u0c35\\u0c3f \\u0c15\\u0c41\\u0c2e\\u0c3e\\u0c30\\u0c4d \\u0c35\\u0c3f\\u0c36\\u0c4d\\u0c35\\u0c28\\u0c3e\\u0c27",
2456
 
        "\\u0c06\\u0c26\\u0c3f\\u0c24\\u0c4d\\u0c2f \\u0C15\\u0C02\\u0C26\\u0C4D\\u0C30\\u0C47\\u0C17\\u0C41\\u0c32",
2457
 
        "\\u0c36\\u0c4d\\u0c30\\u0c40\\u0C27\\u0C30\\u0C4D \\u0c15\\u0c02\\u0c1f\\u0c2e\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f",
2458
 
        "\\u0c2e\\u0c3e\\u0c27\\u0c35\\u0c4d \\u0c26\\u0c46\\u0c36\\u0c46\\u0c1f\\u0c4d\\u0c1f\\u0c3f",
2459
 
    };
2460
 
 
2461
 
    UErrorCode status = U_ZERO_ERROR;
2462
 
    UParseError parseError;
2463
 
    UnicodeString message;
2464
 
    Transliterator* latinToDev=Transliterator::createInstance("Latin-Telugu", UTRANS_FORWARD, parseError, status);
2465
 
    Transliterator* devToLatin=Transliterator::createInstance("Telugu-Latin", UTRANS_FORWARD, parseError, status);
2466
 
    if(U_FAILURE(status)){
2467
 
        errln("FAIL: construction " +   UnicodeString(" Error: ") + u_errorName(status));
2468
 
        errln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
2469
 
        return;
2470
 
    }
2471
 
    UnicodeString gotResult;
2472
 
    for(int i= 0; i<MAX_LEN; i++){
2473
 
        gotResult = source[i];
2474
 
        expect(*latinToDev,CharsToUnicodeString(source[i]),CharsToUnicodeString(expected[i]));
2475
 
        expect(*devToLatin,CharsToUnicodeString(expected[i]),CharsToUnicodeString(source[i]));
2476
 
    }
2477
 
    delete latinToDev;
2478
 
    delete devToLatin;
2479
 
}
2480
 
 
2481
 
void TransliteratorTest::TestSanskritLatinRT(){
2482
 
    const int MAX_LEN =16;
2483
 
    const char* const source[MAX_LEN] = {
2484
 
        "rmk\\u1E63\\u0113t",
2485
 
        "\\u015Br\\u012Bmad",
2486
 
        "bhagavadg\\u012Bt\\u0101",
2487
 
        "adhy\\u0101ya",
2488
 
        "arjuna",
2489
 
        "vi\\u1E63\\u0101da",
2490
 
        "y\\u014Dga",
2491
 
        "dhr\\u0325tar\\u0101\\u1E63\\u1E6Dra",
2492
 
        "uv\\u0101cr\\u0325",
2493
 
        "dharmak\\u1E63\\u0113tr\\u0113",
2494
 
        "kuruk\\u1E63\\u0113tr\\u0113",
2495
 
        "samav\\u0113t\\u0101",
2496
 
        "yuyutsava\\u1E25",
2497
 
        "m\\u0101mak\\u0101\\u1E25",
2498
 
    // "p\\u0101\\u1E47\\u1E0Dav\\u0101\\u015Bcaiva",
2499
 
        "kimakurvata",
2500
 
        "san\\u0304java",
2501
 
    };
2502
 
    const char* const expected[MAX_LEN] = {
2503
 
        "\\u0930\\u094D\\u092E\\u094D\\u0915\\u094D\\u0937\\u0947\\u0924\\u094D",
2504
 
        "\\u0936\\u094d\\u0930\\u0940\\u092e\\u0926\\u094d",
2505
 
        "\\u092d\\u0917\\u0935\\u0926\\u094d\\u0917\\u0940\\u0924\\u093e",
2506
 
        "\\u0905\\u0927\\u094d\\u092f\\u093e\\u092f",
2507
 
        "\\u0905\\u0930\\u094d\\u091c\\u0941\\u0928",
2508
 
        "\\u0935\\u093f\\u0937\\u093e\\u0926",
2509
 
        "\\u092f\\u094b\\u0917",
2510
 
        "\\u0927\\u0943\\u0924\\u0930\\u093e\\u0937\\u094d\\u091f\\u094d\\u0930",
2511
 
        "\\u0909\\u0935\\u093E\\u091A\\u0943",
2512
 
        "\\u0927\\u0930\\u094d\\u092e\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
2513
 
        "\\u0915\\u0941\\u0930\\u0941\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
2514
 
        "\\u0938\\u092e\\u0935\\u0947\\u0924\\u093e",
2515
 
        "\\u092f\\u0941\\u092f\\u0941\\u0924\\u094d\\u0938\\u0935\\u0903",
2516
 
        "\\u092e\\u093e\\u092e\\u0915\\u093e\\u0903",
2517
 
    //"\\u092a\\u093e\\u0923\\u094d\\u0921\\u0935\\u093e\\u0936\\u094d\\u091a\\u0948\\u0935",
2518
 
        "\\u0915\\u093f\\u092e\\u0915\\u0941\\u0930\\u094d\\u0935\\u0924",
2519
 
        "\\u0938\\u0902\\u091c\\u0935",
2520
 
    };
2521
 
    UErrorCode status = U_ZERO_ERROR;
2522
 
    UParseError parseError;
2523
 
    UnicodeString message;
2524
 
    Transliterator* latinToDev=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
2525
 
    Transliterator* devToLatin=Transliterator::createInstance("Devanagari-Latin", UTRANS_FORWARD, parseError, status);
2526
 
    if(U_FAILURE(status)){
2527
 
        errln("FAIL: construction " +   UnicodeString(" Error: ") + u_errorName(status));
2528
 
        errln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
2529
 
        return;
2530
 
    }
2531
 
    UnicodeString gotResult;
2532
 
    for(int i= 0; i<MAX_LEN; i++){
2533
 
        gotResult = source[i];
2534
 
        expect(*latinToDev,CharsToUnicodeString(source[i]),CharsToUnicodeString(expected[i]));
2535
 
        expect(*devToLatin,CharsToUnicodeString(expected[i]),CharsToUnicodeString(source[i]));
2536
 
    }
2537
 
    delete latinToDev;
2538
 
    delete devToLatin;
2539
 
}
2540
 
 
2541
 
 
2542
 
void TransliteratorTest::TestCompoundLatinRT(){
2543
 
    const char* const source[] = {
2544
 
        "rmk\\u1E63\\u0113t",
2545
 
        "\\u015Br\\u012Bmad",
2546
 
        "bhagavadg\\u012Bt\\u0101",
2547
 
        "adhy\\u0101ya",
2548
 
        "arjuna",
2549
 
        "vi\\u1E63\\u0101da",
2550
 
        "y\\u014Dga",
2551
 
        "dhr\\u0325tar\\u0101\\u1E63\\u1E6Dra",
2552
 
        "uv\\u0101cr\\u0325",
2553
 
        "dharmak\\u1E63\\u0113tr\\u0113",
2554
 
        "kuruk\\u1E63\\u0113tr\\u0113",
2555
 
        "samav\\u0113t\\u0101",
2556
 
        "yuyutsava\\u1E25",
2557
 
        "m\\u0101mak\\u0101\\u1E25",
2558
 
     // "p\\u0101\\u1E47\\u1E0Dav\\u0101\\u015Bcaiva",
2559
 
        "kimakurvata",
2560
 
        "san\\u0304java"
2561
 
    };
2562
 
    const int MAX_LEN = sizeof(source)/sizeof(source[0]);
2563
 
    const char* const expected[MAX_LEN] = {
2564
 
        "\\u0930\\u094D\\u092E\\u094D\\u0915\\u094D\\u0937\\u0947\\u0924\\u094D",
2565
 
        "\\u0936\\u094d\\u0930\\u0940\\u092e\\u0926\\u094d",
2566
 
        "\\u092d\\u0917\\u0935\\u0926\\u094d\\u0917\\u0940\\u0924\\u093e",
2567
 
        "\\u0905\\u0927\\u094d\\u092f\\u093e\\u092f",
2568
 
        "\\u0905\\u0930\\u094d\\u091c\\u0941\\u0928",
2569
 
        "\\u0935\\u093f\\u0937\\u093e\\u0926",
2570
 
        "\\u092f\\u094b\\u0917",
2571
 
        "\\u0927\\u0943\\u0924\\u0930\\u093e\\u0937\\u094d\\u091f\\u094d\\u0930",
2572
 
        "\\u0909\\u0935\\u093E\\u091A\\u0943",
2573
 
        "\\u0927\\u0930\\u094d\\u092e\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
2574
 
        "\\u0915\\u0941\\u0930\\u0941\\u0915\\u094d\\u0937\\u0947\\u0924\\u094d\\u0930\\u0947",
2575
 
        "\\u0938\\u092e\\u0935\\u0947\\u0924\\u093e",
2576
 
        "\\u092f\\u0941\\u092f\\u0941\\u0924\\u094d\\u0938\\u0935\\u0903",
2577
 
        "\\u092e\\u093e\\u092e\\u0915\\u093e\\u0903",
2578
 
    //  "\\u092a\\u093e\\u0923\\u094d\\u0921\\u0935\\u093e\\u0936\\u094d\\u091a\\u0948\\u0935",
2579
 
        "\\u0915\\u093f\\u092e\\u0915\\u0941\\u0930\\u094d\\u0935\\u0924",
2580
 
        "\\u0938\\u0902\\u091c\\u0935"
2581
 
    };
2582
 
    if(MAX_LEN != sizeof(expected)/sizeof(expected[0])) {
2583
 
        errln("error in TestCompoundLatinRT: source[] and expected[] have different lengths!");
2584
 
        return;
2585
 
    }
2586
 
 
2587
 
    UErrorCode status = U_ZERO_ERROR;
2588
 
    UParseError parseError;
2589
 
    UnicodeString message;
2590
 
    Transliterator* devToLatinToDev  =Transliterator::createInstance("Devanagari-Latin;Latin-Devanagari", UTRANS_FORWARD, parseError, status);
2591
 
    Transliterator* latinToDevToLatin=Transliterator::createInstance("Latin-Devanagari;Devanagari-Latin", UTRANS_FORWARD, parseError, status);
2592
 
    Transliterator* devToTelToDev    =Transliterator::createInstance("Devanagari-Telugu;Telugu-Devanagari", UTRANS_FORWARD, parseError, status);
2593
 
    Transliterator* latinToTelToLatin=Transliterator::createInstance("Latin-Telugu;Telugu-Latin", UTRANS_FORWARD, parseError, status);
2594
 
 
2595
 
    if(U_FAILURE(status)){
2596
 
        errln("FAIL: construction " +   UnicodeString(" Error: ") + u_errorName(status));
2597
 
        errln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
2598
 
        return;
2599
 
    }
2600
 
    UnicodeString gotResult;
2601
 
    for(int i= 0; i<MAX_LEN; i++){
2602
 
        gotResult = source[i];
2603
 
        expect(*devToLatinToDev,CharsToUnicodeString(expected[i]),CharsToUnicodeString(expected[i]));
2604
 
        expect(*latinToDevToLatin,CharsToUnicodeString(source[i]),CharsToUnicodeString(source[i]));
2605
 
        expect(*latinToTelToLatin,CharsToUnicodeString(source[i]),CharsToUnicodeString(source[i]));
2606
 
 
2607
 
    }
2608
 
    delete(latinToDevToLatin);
2609
 
    delete(devToLatinToDev);  
2610
 
    delete(devToTelToDev);    
2611
 
    delete(latinToTelToLatin);
2612
 
}
2613
 
 
2614
 
/**
2615
 
 * Test instantiation from a locale.
2616
 
 */
2617
 
void TransliteratorTest::TestLocaleInstantiation(void) {
2618
 
    UParseError pe;
2619
 
    UErrorCode ec = U_ZERO_ERROR;
2620
 
    Transliterator *t = Transliterator::createInstance("ru_RU-Latin", UTRANS_FORWARD, pe, ec);
2621
 
    if (U_FAILURE(ec)) {
2622
 
        errln("FAIL: createInstance(ru_RU-Latin)");
2623
 
        delete t;
2624
 
        return;
2625
 
    }
2626
 
    expect(*t, CharsToUnicodeString("\\u0430"), "a");
2627
 
    delete t;
2628
 
    
2629
 
    t = Transliterator::createInstance("en-el", UTRANS_FORWARD, pe, ec);
2630
 
    if (U_FAILURE(ec)) {
2631
 
        errln("FAIL: createInstance(en-el)");
2632
 
        delete t;
2633
 
        return;
2634
 
    }
2635
 
    expect(*t, "a", CharsToUnicodeString("\\u03B1"));
2636
 
    delete t;
2637
 
}
2638
 
        
2639
 
/**
2640
 
 * Test title case handling of accent (should ignore accents)
2641
 
 */
2642
 
void TransliteratorTest::TestTitleAccents(void) {
2643
 
    UParseError pe;
2644
 
    UErrorCode ec = U_ZERO_ERROR;
2645
 
    Transliterator *t = Transliterator::createInstance("Title", UTRANS_FORWARD, pe, ec);
2646
 
    if (U_FAILURE(ec)) {
2647
 
        errln("FAIL: createInstance(Title)");
2648
 
        delete t;
2649
 
        return;
2650
 
    }
2651
 
    expect(*t, CharsToUnicodeString("a\\u0300b can't abe"), CharsToUnicodeString("A\\u0300b Can't Abe"));
2652
 
    delete t;
2653
 
}
2654
 
 
2655
 
/**
2656
 
 * Basic test of a locale resource based rule.
2657
 
 */
2658
 
void TransliteratorTest::TestLocaleResource() {
2659
 
    const char* DATA[] = {
2660
 
        // id                    from               to
2661
 
        //"Latin-Greek/UNGEGN",    "b",               "\\u03bc\\u03c0",
2662
 
        "Latin-el",              "b",               "\\u03bc\\u03c0",
2663
 
        "Latin-Greek",           "b",               "\\u03B2",
2664
 
        "Greek-Latin/UNGEGN",    "\\u03B2",         "v",
2665
 
        "el-Latin",              "\\u03B2",         "v",
2666
 
        "Greek-Latin",           "\\u03B2",         "b",
2667
 
    };
2668
 
    const int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]);
2669
 
    for (int32_t i=0; i<DATA_length; i+=3) {
2670
 
        UParseError pe;
2671
 
        UErrorCode ec = U_ZERO_ERROR;
2672
 
        Transliterator *t = Transliterator::createInstance(DATA[i], UTRANS_FORWARD, pe, ec);
2673
 
        if (U_FAILURE(ec)) {
2674
 
            errln((UnicodeString)"FAIL: createInstance(" + DATA[i] + ")");
2675
 
            delete t;
2676
 
            continue;
2677
 
        }
2678
 
        expect(*t, CharsToUnicodeString(DATA[i+1]),
2679
 
               CharsToUnicodeString(DATA[i+2]));
2680
 
        delete t;
2681
 
    }
2682
 
}
2683
 
 
2684
 
/**
2685
 
 * Make sure parse errors reference the right line.
2686
 
 */
2687
 
void TransliteratorTest::TestParseError() {
2688
 
    const char* rule =
2689
 
        "a > b;\n"
2690
 
        "# more stuff\n"
2691
 
        "d << b;";
2692
 
    UErrorCode ec = U_ZERO_ERROR;
2693
 
    UParseError pe;
2694
 
    Transliterator *t = Transliterator::createFromRules("ID", rule, UTRANS_FORWARD, pe, ec);
2695
 
    delete t;
2696
 
    if (U_FAILURE(ec)) {
2697
 
        UnicodeString err(pe.preContext);
2698
 
        err.append((UChar)124/*|*/).append(pe.postContext);
2699
 
        if (err.indexOf("d << b") >= 0) {
2700
 
            logln("Ok: " + err);
2701
 
        } else {
2702
 
            errln("FAIL: " + err);
2703
 
        }
2704
 
        return;
2705
 
    }
2706
 
    errln("FAIL: no syntax error");
2707
 
}
2708
 
 
2709
 
/**
2710
 
 * Make sure sets on output are disallowed.
2711
 
 */
2712
 
void TransliteratorTest::TestOutputSet() {
2713
 
    UnicodeString rule = "$set = [a-cm-n]; b > $set;";
2714
 
    UErrorCode ec = U_ZERO_ERROR;
2715
 
    UParseError pe;
2716
 
    Transliterator *t = Transliterator::createFromRules("ID", rule, UTRANS_FORWARD, pe, ec);
2717
 
    delete t;
2718
 
    if (U_FAILURE(ec)) {
2719
 
        UnicodeString err(pe.preContext);
2720
 
        err.append((UChar)124/*|*/).append(pe.postContext);
2721
 
        logln("Ok: " + err);
2722
 
        return;
2723
 
    }
2724
 
    errln("FAIL: No syntax error");
2725
 
}        
2726
 
 
2727
 
/**
2728
 
 * Test the use variable range pragma, making sure that use of
2729
 
 * variable range characters is detected and flagged as an error.
2730
 
 */
2731
 
void TransliteratorTest::TestVariableRange() {
2732
 
    UnicodeString rule = "use variable range 0x70 0x72; a > A; b > B; q > Q;";
2733
 
    UErrorCode ec = U_ZERO_ERROR;
2734
 
    UParseError pe;
2735
 
    Transliterator *t = Transliterator::createFromRules("ID", rule, UTRANS_FORWARD, pe, ec);
2736
 
    delete t;
2737
 
    if (U_FAILURE(ec)) {
2738
 
        UnicodeString err(pe.preContext);
2739
 
        err.append((UChar)124/*|*/).append(pe.postContext);
2740
 
        logln("Ok: " + err);
2741
 
        return;
2742
 
    }
2743
 
    errln("FAIL: No syntax error");
2744
 
}
2745
 
 
2746
 
/**
2747
 
 * Test invalid post context error handling
2748
 
 */
2749
 
void TransliteratorTest::TestInvalidPostContext() {
2750
 
    UnicodeString rule = "a}b{c>d;";
2751
 
    UErrorCode ec = U_ZERO_ERROR;
2752
 
    UParseError pe;
2753
 
    Transliterator *t = Transliterator::createFromRules("ID", rule, UTRANS_FORWARD, pe, ec);
2754
 
    delete t;
2755
 
    if (U_FAILURE(ec)) {
2756
 
        UnicodeString err(pe.preContext);
2757
 
        err.append((UChar)124/*|*/).append(pe.postContext);
2758
 
        if (err.indexOf("a}b{c") >= 0) {
2759
 
            logln("Ok: " + err);
2760
 
        } else {
2761
 
            errln("FAIL: " + err);
2762
 
        }
2763
 
        return;
2764
 
    }
2765
 
    errln("FAIL: No syntax error");
2766
 
}
2767
 
 
2768
 
/**
2769
 
 * Test ID form variants
2770
 
 */
2771
 
void TransliteratorTest::TestIDForms() {
2772
 
    const char* DATA[] = {
2773
 
        "NFC", NULL, "NFD",
2774
 
        "nfd", NULL, "NFC", // make sure case is ignored
2775
 
        "Any-NFKD", NULL, "Any-NFKC",
2776
 
        "Null", NULL, "Null",
2777
 
        "-nfkc", "nfkc", "NFKD",
2778
 
        "-nfkc/", "nfkc", "NFKD",
2779
 
        "Latin-Greek/UNGEGN", NULL, "Greek-Latin/UNGEGN",
2780
 
        "Greek/UNGEGN-Latin", "Greek-Latin/UNGEGN", "Latin-Greek/UNGEGN",
2781
 
        "Bengali-Devanagari/", "Bengali-Devanagari", "Devanagari-Bengali",
2782
 
        "Source-", NULL, NULL,
2783
 
        "Source/Variant-", NULL, NULL,
2784
 
        "Source-/Variant", NULL, NULL,
2785
 
        "/Variant", NULL, NULL,
2786
 
        "/Variant-", NULL, NULL,
2787
 
        "-/Variant", NULL, NULL,
2788
 
        "-/", NULL, NULL,
2789
 
        "-", NULL, NULL,
2790
 
        "/", NULL, NULL,
2791
 
    };
2792
 
    const int32_t DATA_length = sizeof(DATA)/sizeof(DATA[0]);
2793
 
    
2794
 
    for (int32_t i=0; i<DATA_length; i+=3) {
2795
 
        const char* ID = DATA[i];
2796
 
        const char* expID = DATA[i+1];
2797
 
        const char* expInvID = DATA[i+2];
2798
 
        UBool expValid = (expInvID != NULL);
2799
 
        if (expID == NULL) {
2800
 
            expID = ID;
2801
 
        }
2802
 
        UParseError pe;
2803
 
        UErrorCode ec = U_ZERO_ERROR;
2804
 
        Transliterator *t =
2805
 
            Transliterator::createInstance(ID, UTRANS_FORWARD, pe, ec);
2806
 
        if (U_FAILURE(ec)) {
2807
 
            if (!expValid) {
2808
 
                logln((UnicodeString)"Ok: getInstance(" + ID +") => " + u_errorName(ec));
2809
 
            } else {
2810
 
                errln((UnicodeString)"FAIL: Couldn't create " + ID);
2811
 
            }
2812
 
            delete t;
2813
 
            continue;
2814
 
        }
2815
 
        Transliterator *u = t->createInverse(ec);
2816
 
        if (U_FAILURE(ec)) {
2817
 
            errln((UnicodeString)"FAIL: Couldn't create inverse of " + ID);
2818
 
            delete t;
2819
 
            delete u;
2820
 
            continue;
2821
 
        }
2822
 
        if (t->getID() == expID &&
2823
 
            u->getID() == expInvID) {
2824
 
            logln((UnicodeString)"Ok: " + ID + ".getInverse() => " + expInvID);
2825
 
        } else {
2826
 
            errln((UnicodeString)"FAIL: getInstance(" + ID + ") => " +
2827
 
                  t->getID() + " x getInverse() => " + u->getID() +
2828
 
                  ", expected " + expInvID);
2829
 
        }
2830
 
        delete t;
2831
 
        delete u;
2832
 
    }
2833
 
}
2834
 
 
2835
 
static const UChar SPACE[]   = {32,0};
2836
 
static const UChar NEWLINE[] = {10,0};
2837
 
static const UChar RETURN[]  = {13,0};
2838
 
static const UChar EMPTY[]   = {0};
2839
 
 
2840
 
void TransliteratorTest::checkRules(const UnicodeString& label, Transliterator& t2,
2841
 
                                    const UnicodeString& testRulesForward) {
2842
 
    UnicodeString rules2; t2.toRules(rules2, TRUE);
2843
 
    //rules2 = TestUtility.replaceAll(rules2, new UnicodeSet("[' '\n\r]"), "");
2844
 
    rules2.findAndReplace(SPACE, EMPTY);
2845
 
    rules2.findAndReplace(NEWLINE, EMPTY);
2846
 
    rules2.findAndReplace(RETURN, EMPTY);
2847
 
 
2848
 
    UnicodeString testRules(testRulesForward); testRules.findAndReplace(SPACE, EMPTY);
2849
 
    
2850
 
    if (rules2 != testRules) {
2851
 
        errln(label);
2852
 
        logln((UnicodeString)"GENERATED RULES: " + rules2);
2853
 
        logln((UnicodeString)"SHOULD BE:       " + testRulesForward);
2854
 
    }
2855
 
}
2856
 
 
2857
 
/**
2858
 
 * Mark's toRules test.
2859
 
 */
2860
 
void TransliteratorTest::TestToRulesMark() {
2861
 
    const char* testRules = 
2862
 
        "::[[:Latin:][:Mark:]];"
2863
 
        "::NFKD (NFC);"
2864
 
        "::Lower (Lower);"
2865
 
        "a <> \\u03B1;" // alpha
2866
 
        "::NFKC (NFD);"
2867
 
        "::Upper (Lower);"
2868
 
        "::Lower ();"
2869
 
        "::([[:Greek:][:Mark:]]);"
2870
 
        ;
2871
 
    const char* testRulesForward = 
2872
 
        "::[[:Latin:][:Mark:]];"
2873
 
        "::NFKD(NFC);"
2874
 
        "::Lower(Lower);"
2875
 
        "a > \\u03B1;"
2876
 
        "::NFKC(NFD);"
2877
 
        "::Upper (Lower);"
2878
 
        "::Lower ();"
2879
 
        ;
2880
 
    const char* testRulesBackward = 
2881
 
        "::[[:Greek:][:Mark:]];"
2882
 
        "::Lower (Upper);"
2883
 
        "::NFD(NFKC);"
2884
 
        "\\u03B1 > a;"
2885
 
        "::Lower(Lower);"
2886
 
        "::NFC(NFKD);"
2887
 
        ;
2888
 
    UnicodeString source = CharsToUnicodeString("\\u00E1"); // a-acute
2889
 
    UnicodeString target = CharsToUnicodeString("\\u03AC"); // alpha-acute
2890
 
    
2891
 
    UParseError pe;
2892
 
    UErrorCode ec = U_ZERO_ERROR;
2893
 
    Transliterator *t2 = Transliterator::createFromRules("source-target", testRules, UTRANS_FORWARD, pe, ec);
2894
 
    Transliterator *t3 = Transliterator::createFromRules("target-source", testRules, UTRANS_REVERSE, pe, ec);
2895
 
 
2896
 
    if (U_FAILURE(ec)) {
2897
 
        delete t2;
2898
 
        delete t3;
2899
 
        errln((UnicodeString)"FAIL: createFromRules => " + u_errorName(ec));
2900
 
        return;
2901
 
    }
2902
 
    
2903
 
    expect(*t2, source, target);
2904
 
    expect(*t3, target, source);
2905
 
    
2906
 
    checkRules("Failed toRules FORWARD", *t2, testRulesForward);
2907
 
    checkRules("Failed toRules BACKWARD", *t3, testRulesBackward);
2908
 
 
2909
 
    delete t2;
2910
 
    delete t3;
2911
 
}
2912
 
 
2913
 
/**
2914
 
 * Test Escape and Unescape transliterators.
2915
 
 */
2916
 
void TransliteratorTest::TestEscape() {
2917
 
    UParseError pe;
2918
 
    UErrorCode ec;
2919
 
    Transliterator *t;
2920
 
 
2921
 
    ec = U_ZERO_ERROR;
2922
 
    t = Transliterator::createInstance("Hex-Any", UTRANS_FORWARD, pe, ec);
2923
 
    if (U_FAILURE(ec)) {
2924
 
        errln((UnicodeString)"FAIL: createInstance");
2925
 
    } else {
2926
 
        expect(*t,
2927
 
               "\\x{40}\\U00000031&#x32;&#81;",
2928
 
               "@12Q");
2929
 
    }
2930
 
    delete t;
2931
 
 
2932
 
    ec = U_ZERO_ERROR;
2933
 
    t = Transliterator::createInstance("Any-Hex/C", UTRANS_FORWARD, pe, ec);
2934
 
    if (U_FAILURE(ec)) {
2935
 
        errln((UnicodeString)"FAIL: createInstance");
2936
 
    } else {
2937
 
        expect(*t,
2938
 
               CharsToUnicodeString("A\\U0010BEEF\\uFEED"),
2939
 
               "\\u0041\\U0010BEEF\\uFEED");
2940
 
    }
2941
 
    delete t;
2942
 
 
2943
 
    ec = U_ZERO_ERROR;
2944
 
    t = Transliterator::createInstance("Any-Hex/Java", UTRANS_FORWARD, pe, ec);
2945
 
    if (U_FAILURE(ec)) {
2946
 
        errln((UnicodeString)"FAIL: createInstance");
2947
 
    } else {
2948
 
        expect(*t,
2949
 
               CharsToUnicodeString("A\\U0010BEEF\\uFEED"),
2950
 
               "\\u0041\\uDBEF\\uDEEF\\uFEED");
2951
 
    }
2952
 
    delete t;
2953
 
 
2954
 
    ec = U_ZERO_ERROR;
2955
 
    t = Transliterator::createInstance("Any-Hex/Perl", UTRANS_FORWARD, pe, ec);
2956
 
    if (U_FAILURE(ec)) {
2957
 
        errln((UnicodeString)"FAIL: createInstance");
2958
 
    } else {
2959
 
        expect(*t,
2960
 
               CharsToUnicodeString("A\\U0010BEEF\\uFEED"),
2961
 
               "\\x{41}\\x{10BEEF}\\x{FEED}");
2962
 
    }
2963
 
    delete t;
2964
 
}
2965
 
 
2966
 
 
2967
 
void TransliteratorTest::TestAnchorMasking(){
2968
 
    UnicodeString rule ("^a > Q; a > q;");
2969
 
    UErrorCode status= U_ZERO_ERROR;
2970
 
    UParseError parseError;
2971
 
 
2972
 
    Transliterator* t = Transliterator::createFromRules("ID", rule, UTRANS_FORWARD,parseError,status);
2973
 
    if(U_FAILURE(status)){
2974
 
        errln(UnicodeString("FAIL: ") + "ID" +
2975
 
              ".createFromRules() => bad rules" +
2976
 
              /*", parse error " + parseError.code +*/
2977
 
              ", line " + parseError.line +
2978
 
              ", offset " + parseError.offset +
2979
 
              ", context " + prettify(parseError.preContext, TRUE) +
2980
 
              ", rules: " + prettify(rule, TRUE));
2981
 
    }
2982
 
    delete t;
2983
 
}
2984
 
 
2985
 
/**
2986
 
 * Make sure display names of variants look reasonable.
2987
 
 */
2988
 
void TransliteratorTest::TestDisplayName() {
2989
 
    static const char* DATA[] = {
2990
 
        // ID, forward name, reverse name
2991
 
        // Update the text as necessary -- the important thing is
2992
 
        // not the text itself, but how various cases are handled.
2993
 
        
2994
 
        // Basic test
2995
 
        "Any-Hex", "Any to Hex Escape", "Hex Escape to Any",
2996
 
        
2997
 
        // Variants
2998
 
        "Any-Hex/Perl", "Any to Hex Escape/Perl", "Hex Escape to Any/Perl",
2999
 
        
3000
 
        // Target-only IDs
3001
 
        "NFC", "Any to NFC", "Any to NFD",
3002
 
    };
3003
 
 
3004
 
    int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]);
3005
 
    
3006
 
    Locale US("en", "US");
3007
 
    
3008
 
    for (int32_t i=0; i<DATA_length; i+=3) {
3009
 
        UnicodeString name;
3010
 
        Transliterator::getDisplayName(DATA[i], US, name);
3011
 
        if (name != DATA[i+1]) {
3012
 
            errln((UnicodeString)"FAIL: " + DATA[i] + ".getDisplayName() => " +
3013
 
                  name + ", expected " + DATA[i+1]);
3014
 
        } else {
3015
 
            logln((UnicodeString)"Ok: " + DATA[i] + ".getDisplayName() => " + name);
3016
 
        }
3017
 
        UErrorCode ec = U_ZERO_ERROR;
3018
 
        UParseError pe;
3019
 
        Transliterator *t = Transliterator::createInstance(DATA[i], UTRANS_REVERSE, pe, ec);
3020
 
        if (U_FAILURE(ec)) {
3021
 
            delete t;
3022
 
            errln("FAIL: createInstance failed");
3023
 
            continue;
3024
 
        }
3025
 
        name = Transliterator::getDisplayName(t->getID(), US, name);
3026
 
        if (name != DATA[i+2]) {
3027
 
            errln((UnicodeString)"FAIL: " + t->getID() + ".getDisplayName() => " +
3028
 
                  name + ", expected " + DATA[i+2]);
3029
 
        } else {
3030
 
            logln((UnicodeString)"Ok: " + t->getID() + ".getDisplayName() => " + name);
3031
 
        }
3032
 
        delete t;
3033
 
    }
3034
 
}
3035
 
 
3036
 
void TransliteratorTest::TestSpecialCases(void) {
3037
 
    const UnicodeString registerRules[] = {
3038
 
        "Any-Dev1", "x > X; y > Y;",
3039
 
        "Any-Dev2", "XY > Z",
3040
 
        "Greek-Latin/FAKE", 
3041
 
            CharsToUnicodeString
3042
 
            ("[^[:L:][:M:]] { \\u03bc\\u03c0 > b ; \\u03bc\\u03c0 } [^[:L:][:M:]] > b ; [^[:L:][:M:]] { [\\u039c\\u03bc][\\u03a0\\u03c0] > B ; [\\u039c\\u03bc][\\u03a0\\u03c0] } [^[:L:][:M:]] > B ;"),
3043
 
        "" // END MARKER
3044
 
    };
3045
 
 
3046
 
    static const UnicodeString testCases[] = {
3047
 
        // NORMALIZATION
3048
 
        // should add more test cases
3049
 
        "NFD" , CharsToUnicodeString("a\\u0300 \\u00E0 \\u1100\\u1161 \\uFF76\\uFF9E\\u03D3"), "",
3050
 
        "NFC" , CharsToUnicodeString("a\\u0300 \\u00E0 \\u1100\\u1161 \\uFF76\\uFF9E\\u03D3"), "",
3051
 
        "NFKD", CharsToUnicodeString("a\\u0300 \\u00E0 \\u1100\\u1161 \\uFF76\\uFF9E\\u03D3"), "",
3052
 
        "NFKC", CharsToUnicodeString("a\\u0300 \\u00E0 \\u1100\\u1161 \\uFF76\\uFF9E\\u03D3"), "",
3053
 
 
3054
 
        // mp -> b BUG
3055
 
        "Greek-Latin/UNGEGN", CharsToUnicodeString("(\\u03BC\\u03C0)"), "(b)",
3056
 
        "Greek-Latin/FAKE", CharsToUnicodeString("(\\u03BC\\u03C0)"), "(b)",
3057
 
    
3058
 
        // check for devanagari bug
3059
 
        "nfd;Dev1;Dev2;nfc", "xy", "Z",
3060
 
 
3061
 
        // ff, i, dotless-i, I, dotted-I, LJLjlj deseret deeDEE
3062
 
        "Title", CharsToUnicodeString("ab'cD ffi\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, 
3063
 
                 CharsToUnicodeString("Ab'cd Ffi\\u0131ii \\u01C8\\u01C9\\u01C9 ") + DESERET_DEE + DESERET_dee, 
3064
 
                 
3065
 
        //TODO: enable this test once Titlecase works right
3066
 
        /*
3067
 
        "Title", CharsToUnicodeString("\\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, 
3068
 
                 CharsToUnicodeString("Ffi\\u0131ii \\u01C8\\u01C9\\u01C9 ") + DESERET_DEE + DESERET_dee, 
3069
 
                 */
3070
 
        "Upper", CharsToUnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, 
3071
 
                 CharsToUnicodeString("AB'CD FFIII\\u0130 \\u01C7\\u01C7\\u01C7 ") + DESERET_DEE + DESERET_DEE,
3072
 
        "Lower", CharsToUnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, 
3073
 
                 CharsToUnicodeString("ab'cd \\uFB00i\\u0131ii \\u01C9\\u01C9\\u01C9 ") + DESERET_dee + DESERET_dee,
3074
 
    
3075
 
        "Upper", CharsToUnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, "",
3076
 
        "Lower", CharsToUnicodeString("ab'cD \\uFB00i\\u0131I\\u0130 \\u01C7\\u01C8\\u01C9 ") + DESERET_dee + DESERET_DEE, "",
3077
 
 
3078
 
         // FORMS OF S
3079
 
        "Greek-Latin/UNGEGN",  CharsToUnicodeString("\\u03C3 \\u03C3\\u03C2 \\u03C2\\u03C3"), 
3080
 
                               CharsToUnicodeString("s ss s\\u0331s\\u0331") ,
3081
 
        "Latin-Greek/UNGEGN",  CharsToUnicodeString("s ss s\\u0331s\\u0331"), 
3082
 
                               CharsToUnicodeString("\\u03C3 \\u03C3\\u03C2 \\u03C2\\u03C3") ,
3083
 
        "Greek-Latin",  CharsToUnicodeString("\\u03C3 \\u03C3\\u03C2 \\u03C2\\u03C3"), 
3084
 
                        CharsToUnicodeString("s ss s\\u0331s\\u0331") ,
3085
 
        "Latin-Greek",  CharsToUnicodeString("s ss s\\u0331s\\u0331"), 
3086
 
                        CharsToUnicodeString("\\u03C3 \\u03C3\\u03C2 \\u03C2\\u03C3"),
3087
 
        // Tatiana bug
3088
 
        // Upper: TAT\\u02B9\\u00C2NA
3089
 
        // Lower: tat\\u02B9\\u00E2na
3090
 
        // Title: Tat\\u02B9\\u00E2na
3091
 
        "Upper", CharsToUnicodeString("tat\\u02B9\\u00E2na"),
3092
 
                 CharsToUnicodeString("TAT\\u02B9\\u00C2NA"),
3093
 
        "Lower", CharsToUnicodeString("TAT\\u02B9\\u00C2NA"),
3094
 
                 CharsToUnicodeString("tat\\u02B9\\u00E2na"),
3095
 
        "Title", CharsToUnicodeString("tat\\u02B9\\u00E2na"),
3096
 
                 CharsToUnicodeString("Tat\\u02B9\\u00E2na"),
3097
 
 
3098
 
        "" // END MARKER
3099
 
    };
3100
 
 
3101
 
    UParseError pos;
3102
 
    int32_t i;
3103
 
    for (i = 0; registerRules[i].length()!=0; i+=2) {
3104
 
        UErrorCode status = U_ZERO_ERROR;
3105
 
 
3106
 
        Transliterator *t = Transliterator::createFromRules(registerRules[0+i], 
3107
 
            registerRules[i+1], UTRANS_FORWARD, pos, status);
3108
 
        if (U_FAILURE(status)) {
3109
 
            errln("Fails: Unable to create the transliterator from rules.");
3110
 
        } else {
3111
 
            Transliterator::registerInstance(t);
3112
 
        }
3113
 
    }
3114
 
    for (i = 0; testCases[i].length()!=0; i+=3) {
3115
 
        UErrorCode ec = U_ZERO_ERROR;
3116
 
        UParseError pe;
3117
 
        const UnicodeString& name = testCases[i];
3118
 
        Transliterator *t = Transliterator::createInstance(name, UTRANS_FORWARD, pe, ec);
3119
 
        if (U_FAILURE(ec)) {
3120
 
            errln((UnicodeString)"FAIL: Couldn't create " + name);
3121
 
            delete t;
3122
 
            continue;
3123
 
        }
3124
 
        const UnicodeString& id = t->getID();
3125
 
        const UnicodeString& source = testCases[i+1];
3126
 
        UnicodeString target;
3127
 
 
3128
 
        // Automatic generation of targets, to make it simpler to add test cases (and more fail-safe)
3129
 
        
3130
 
        if (testCases[i+2].length() > 0) {
3131
 
            target = testCases[i+2];
3132
 
        } else if (0==id.caseCompare("NFD", U_FOLD_CASE_DEFAULT)) {
3133
 
            Normalizer::normalize(source, UNORM_NFD, 0, target, ec);
3134
 
        } else if (0==id.caseCompare("NFC", U_FOLD_CASE_DEFAULT)) {
3135
 
            Normalizer::normalize(source, UNORM_NFC, 0, target, ec);
3136
 
        } else if (0==id.caseCompare("NFKD", U_FOLD_CASE_DEFAULT)) {
3137
 
            Normalizer::normalize(source, UNORM_NFKD, 0, target, ec);
3138
 
        } else if (0==id.caseCompare("NFKC", U_FOLD_CASE_DEFAULT)) {
3139
 
            Normalizer::normalize(source, UNORM_NFKC, 0, target, ec);
3140
 
        } else if (0==id.caseCompare("Lower", U_FOLD_CASE_DEFAULT)) {
3141
 
            target = source;
3142
 
            target.toLower(Locale::US);
3143
 
        } else if (0==id.caseCompare("Upper", U_FOLD_CASE_DEFAULT)) {
3144
 
            target = source;
3145
 
            target.toUpper(Locale::US);
3146
 
        }
3147
 
        if (U_FAILURE(ec)) {
3148
 
            errln((UnicodeString)"FAIL: Internal error normalizing " + source);
3149
 
            continue;
3150
 
        }
3151
 
 
3152
 
        expect(*t, source, target);
3153
 
        delete t;
3154
 
    }
3155
 
    for (i = 0; registerRules[i].length()!=0; i+=2) {
3156
 
        Transliterator::unregister(registerRules[i]);
3157
 
    }
3158
 
}
3159
 
 
3160
 
char* Char32ToEscapedChars(UChar32 ch, char* buffer) {
3161
 
    if (ch <= 0xFFFF) {
3162
 
        sprintf(buffer, "\\u%04x", ch);
3163
 
    } else {
3164
 
        sprintf(buffer, "\\u%08x", ch);
3165
 
    }
3166
 
    return buffer;
3167
 
}
3168
 
 
3169
 
void TransliteratorTest::TestSurrogateCasing (void) {
3170
 
    // check that casing handles surrogates
3171
 
    // titlecase is currently defective
3172
 
    char buffer[20];
3173
 
    UChar buffer2[20];
3174
 
    UChar32 dee;
3175
 
    UTF_GET_CHAR(DESERET_dee,0, 0, DESERET_dee.length(), dee);
3176
 
    UnicodeString DEE(u_totitle(dee));
3177
 
    if (DEE != DESERET_DEE) {
3178
 
        err("Fails titlecase of surrogates");
3179
 
        err(Char32ToEscapedChars(dee, buffer)); 
3180
 
        err(", ");
3181
 
        errln(Char32ToEscapedChars(DEE.char32At(0), buffer));
3182
 
    }
3183
 
        
3184
 
    UnicodeString deeDEETest=DESERET_dee + DESERET_DEE;
3185
 
    UnicodeString deedeeTest = DESERET_dee + DESERET_dee;
3186
 
    UnicodeString DEEDEETest = DESERET_DEE + DESERET_DEE;
3187
 
    UErrorCode status= U_ZERO_ERROR;
3188
 
 
3189
 
    u_strToUpper(buffer2, 20, deeDEETest.getBuffer(), deeDEETest.length(), NULL, &status);
3190
 
    if (U_FAILURE(status) || (UnicodeString(buffer2)!= DEEDEETest)) {
3191
 
        errln("Fails: Can't uppercase surrogates.");
3192
 
    }
3193
 
        
3194
 
    status= U_ZERO_ERROR;
3195
 
    u_strToLower(buffer2, 20, deeDEETest.getBuffer(), deeDEETest.length(), NULL, &status);
3196
 
    if (U_FAILURE(status) || (UnicodeString(buffer2)!= deedeeTest)) {
3197
 
        errln("Fails: Can't lowercase surrogates.");
3198
 
    }
3199
 
}
3200
 
 
3201
 
static void _trans(Transliterator& t, const UnicodeString& src,
3202
 
                   UnicodeString& result) {
3203
 
    result = src;
3204
 
    t.transliterate(result);
3205
 
}
3206
 
 
3207
 
static void _trans(const UnicodeString& id, const UnicodeString& src,
3208
 
                   UnicodeString& result, UErrorCode ec) {
3209
 
    UParseError pe;
3210
 
    Transliterator *t = Transliterator::createInstance(id, UTRANS_FORWARD, pe, ec);
3211
 
    if (U_SUCCESS(ec)) {
3212
 
        _trans(*t, src, result);
3213
 
    }
3214
 
    delete t;
3215
 
}
3216
 
 
3217
 
static const UnicodeString& _findMatch(const UnicodeString& source,
3218
 
                                       const UnicodeString* pairs) {
3219
 
    static const UnicodeString empty;
3220
 
    for (int32_t i=0; pairs[i].length() > 0; i+=2) {
3221
 
        if (0==source.caseCompare(pairs[i], U_FOLD_CASE_DEFAULT)) {
3222
 
            return pairs[i+1];
3223
 
        }
3224
 
    }
3225
 
    return empty;
3226
 
}
3227
 
 
3228
 
// Check to see that incremental gets at least part way through a reasonable string.
3229
 
 
3230
 
void TransliteratorTest::TestIncrementalProgress(void) {
3231
 
    UErrorCode ec = U_ZERO_ERROR;
3232
 
    UnicodeString latinTest = "The Quick Brown Fox.";
3233
 
    UnicodeString devaTest;
3234
 
    _trans("Latin-Devanagari", latinTest, devaTest, ec);
3235
 
    UnicodeString kataTest;
3236
 
    _trans("Latin-Katakana", latinTest, kataTest, ec);
3237
 
    if (U_FAILURE(ec)) {
3238
 
        errln("FAIL: Internal error");
3239
 
        return;
3240
 
    }
3241
 
    static const UnicodeString tests[] = {
3242
 
        "Any", latinTest,
3243
 
        "Latin", latinTest,
3244
 
        "Halfwidth", latinTest,
3245
 
        "Devanagari", devaTest,
3246
 
        "Katakana", kataTest,
3247
 
        "" // END MARKER
3248
 
    };
3249
 
 
3250
 
    UnicodeString test("The Quick Brown Fox Jumped Over The Lazy Dog.");
3251
 
    int32_t i = 0, j=0, k=0;
3252
 
    int32_t sources = Transliterator::countAvailableSources();
3253
 
    for (i = 0; i < sources; i++) {
3254
 
        UnicodeString source;
3255
 
        Transliterator::getAvailableSource(i, source);
3256
 
        UnicodeString test = _findMatch(source, tests);
3257
 
        if (test.length() == 0) {
3258
 
            logln((UnicodeString)"Skipping " + source + "-X");
3259
 
            continue;
3260
 
        }
3261
 
        int32_t targets = Transliterator::countAvailableTargets(source);
3262
 
        for (j = 0; j < targets; j++) {
3263
 
            UnicodeString target;
3264
 
            Transliterator::getAvailableTarget(j, source, target);
3265
 
            int32_t variants = Transliterator::countAvailableVariants(source, target);
3266
 
            for (k =0; k< variants; k++) {
3267
 
                UnicodeString variant;
3268
 
                UParseError err;
3269
 
                UErrorCode status = U_ZERO_ERROR;
3270
 
 
3271
 
                Transliterator::getAvailableVariant(k, source, target, variant);
3272
 
                UnicodeString id = source + "-" + target + "/" + variant;
3273
 
    
3274
 
                Transliterator *t = Transliterator::createInstance(id, UTRANS_FORWARD, err, status);
3275
 
                if (U_FAILURE(status)) {
3276
 
                    errln((UnicodeString)"FAIL: Could not create " + id);
3277
 
                    delete t;
3278
 
                    continue;
3279
 
                }
3280
 
                status = U_ZERO_ERROR;
3281
 
                CheckIncrementalAux(t, test);
3282
 
 
3283
 
                UnicodeString rev;
3284
 
                _trans(*t, test, rev);
3285
 
                Transliterator *inv = t->createInverse(status);
3286
 
                if (U_FAILURE(status)) {
3287
 
                    errln((UnicodeString)"FAIL: Could not create inverse of " + id);
3288
 
                    delete t;
3289
 
                    delete inv;
3290
 
                    continue;
3291
 
                }
3292
 
                CheckIncrementalAux(inv, rev);
3293
 
                delete t;
3294
 
                delete inv;
3295
 
            }
3296
 
        }
3297
 
    }
3298
 
}
3299
 
 
3300
 
void TransliteratorTest::CheckIncrementalAux(const Transliterator* t, 
3301
 
                                                      const UnicodeString& input) {
3302
 
    UErrorCode ec = U_ZERO_ERROR;
3303
 
    UTransPosition pos;
3304
 
    UnicodeString test = input;
3305
 
 
3306
 
    pos.contextStart = 0;
3307
 
    pos.contextLimit = input.length();
3308
 
    pos.start = 0;
3309
 
    pos.limit = input.length();
3310
 
 
3311
 
    t->transliterate(test, pos, ec);
3312
 
    if (U_FAILURE(ec)) {
3313
 
        errln((UnicodeString)"FAIL: transliterate() error " + u_errorName(ec));
3314
 
        return;
3315
 
    }
3316
 
    UBool gotError = FALSE;
3317
 
 
3318
 
    // we have a few special cases. Any-Remove (pos.start = 0, but also = limit) and U+XXXXX?X?
3319
 
 
3320
 
    if (pos.start == 0 && pos.limit != 0 && t->getID() != "Hex-Any/Unicode") {
3321
 
        errln((UnicodeString)"No Progress, " +
3322
 
              t->getID() + ": " + formatInput(test, input, pos));
3323
 
        gotError = TRUE;
3324
 
    } else {
3325
 
        logln((UnicodeString)"PASS Progress, " +
3326
 
              t->getID() + ": " + formatInput(test, input, pos));
3327
 
    }
3328
 
    t->finishTransliteration(test, pos);
3329
 
    if (pos.start != pos.limit) {
3330
 
        errln((UnicodeString)"Incomplete, " +
3331
 
              t->getID() + ": " + formatInput(test, input, pos));
3332
 
        gotError = TRUE;
3333
 
    }
3334
 
}
3335
 
 
3336
 
void TransliteratorTest::TestFunction() {
3337
 
    // Careful with spacing and ';' here:  Phrase this exactly
3338
 
    // as toRules() is going to return it.  If toRules() changes
3339
 
    // with regard to spacing or ';', then adjust this string.
3340
 
    UnicodeString rule = // TODO clean up spacing
3341
 
        "([:Lu:]) > $1 '(' &Lower( $1 ) '=' &Hex( &Any-Lower( $1 ) ) ')';";
3342
 
    
3343
 
    UParseError pe;
3344
 
    UErrorCode ec = U_ZERO_ERROR;
3345
 
    Transliterator *t = Transliterator::createFromRules("Test", rule, UTRANS_FORWARD, pe, ec);
3346
 
    if (t == NULL) {
3347
 
        errln("FAIL: createFromRules failed");
3348
 
        return;
3349
 
    }
3350
 
    
3351
 
    UnicodeString r;
3352
 
    t->toRules(r, TRUE);
3353
 
    if (r == rule) {
3354
 
        logln((UnicodeString)"OK: toRules() => " + r);
3355
 
    } else {
3356
 
        errln((UnicodeString)"FAIL: toRules() => " + r +
3357
 
              ", expected " + rule);
3358
 
    }
3359
 
    
3360
 
    expect(*t, "The Quick Brown Fox",
3361
 
           "T(t=\\u0074)he Q(q=\\u0071)uick B(b=\\u0062)rown F(f=\\u0066)ox");
3362
 
 
3363
 
    delete t;
3364
 
}
3365
 
 
3366
 
void TransliteratorTest::TestInvalidBackRef(void) {
3367
 
    UnicodeString rule =  ". > $1;";
3368
 
    UnicodeString rule2 =CharsToUnicodeString("(.) <> &hex/unicode($1) &name($1); . > $1; [{}] >\\u0020;");
3369
 
    UParseError pe;
3370
 
    UErrorCode ec = U_ZERO_ERROR;
3371
 
    Transliterator *t = Transliterator::createFromRules("Test", rule, UTRANS_FORWARD, pe, ec);
3372
 
    Transliterator *t2 = Transliterator::createFromRules("Test2", rule2, UTRANS_FORWARD, pe, ec);
3373
 
 
3374
 
    if (t != NULL) {
3375
 
        errln("FAIL: createFromRules should have returned NULL");
3376
 
        delete t;
3377
 
    }
3378
 
 
3379
 
    if (t2 != NULL) {
3380
 
        errln("FAIL: createFromRules should have returned NULL");
3381
 
        delete t2;
3382
 
    }
3383
 
 
3384
 
    if (U_SUCCESS(ec)) {
3385
 
        errln("FAIL: Ok: . > $1; => no error");
3386
 
    } else {
3387
 
        logln((UnicodeString)"Ok: . > $1; => " + u_errorName(ec));
3388
 
    }
3389
 
}
3390
 
 
3391
 
//======================================================================
3392
 
// Support methods
3393
 
//======================================================================
3394
 
void TransliteratorTest::expectT(const UnicodeString& id,
3395
 
                                 const UnicodeString& source,
3396
 
                                 const UnicodeString& expectedResult) {
3397
 
    UErrorCode ec = U_ZERO_ERROR;
3398
 
    UParseError pe;
3399
 
    Transliterator *t = Transliterator::createInstance(id, UTRANS_FORWARD, pe, ec);
3400
 
    if (U_FAILURE(ec)) {
3401
 
        errln((UnicodeString)"FAIL: Could not create " + id);
3402
 
        delete t;
3403
 
        return;
3404
 
    }
3405
 
    expect(*t, source, expectedResult);
3406
 
    delete t;
3407
 
}
3408
 
 
3409
 
void TransliteratorTest::expect(const UnicodeString& rules,
3410
 
                                const UnicodeString& source,
3411
 
                                const UnicodeString& expectedResult,
3412
 
                                UTransPosition *pos) {
3413
 
    UErrorCode status = U_ZERO_ERROR;
3414
 
    Transliterator *t = new RuleBasedTransliterator("<ID>", rules, status);
3415
 
    if (U_FAILURE(status)) {
3416
 
        errln("FAIL: Transliterator constructor failed");
3417
 
    } else {
3418
 
        expect(*t, source, expectedResult, pos);
3419
 
    }
3420
 
    delete t;
3421
 
}
3422
 
 
3423
 
void TransliteratorTest::expect(const Transliterator& t,
3424
 
                                const UnicodeString& source,
3425
 
                                const UnicodeString& expectedResult,
3426
 
                                const Transliterator& reverseTransliterator) {
3427
 
    expect(t, source, expectedResult);
3428
 
    expect(reverseTransliterator, expectedResult, source);
3429
 
}
3430
 
 
3431
 
void TransliteratorTest::expect(const Transliterator& t,
3432
 
                                const UnicodeString& source,
3433
 
                                const UnicodeString& expectedResult,
3434
 
                                UTransPosition *pos) {
3435
 
    if (pos == 0) {
3436
 
        UnicodeString result(source);
3437
 
        t.transliterate(result);
3438
 
        expectAux(t.getID() + ":String", source, result, expectedResult);
3439
 
    }
3440
 
 
3441
 
    UTransPosition index={0, 0, 0, 0};
3442
 
    if (pos != 0) {
3443
 
        index = *pos;
3444
 
    }
3445
 
 
3446
 
    UnicodeString rsource(source);
3447
 
    if (pos == 0) {
3448
 
        t.transliterate(rsource);
3449
 
    } else {
3450
 
        // Do it all at once -- below we do it incrementally
3451
 
        t.finishTransliteration(rsource, *pos);
3452
 
    }
3453
 
    expectAux(t.getID() + ":Replaceable", source, rsource, expectedResult);
3454
 
 
3455
 
    // Test keyboard (incremental) transliteration -- this result
3456
 
    // must be the same after we finalize (see below).
3457
 
    UnicodeString log;
3458
 
    rsource.remove();
3459
 
    if (pos != 0) {
3460
 
        rsource = source;
3461
 
        formatInput(log, rsource, index);
3462
 
        log.append(" -> ");
3463
 
        UErrorCode status = U_ZERO_ERROR;
3464
 
        t.transliterate(rsource, index, status);
3465
 
        formatInput(log, rsource, index);
3466
 
    } else {
3467
 
        for (int32_t i=0; i<source.length(); ++i) {
3468
 
            if (i != 0) {
3469
 
                log.append(" + ");
3470
 
            }
3471
 
            log.append(source.charAt(i)).append(" -> ");
3472
 
            UErrorCode status = U_ZERO_ERROR;
3473
 
            t.transliterate(rsource, index, source.charAt(i), status);
3474
 
            formatInput(log, rsource, index);
3475
 
        }
3476
 
    }
3477
 
    
3478
 
    // As a final step in keyboard transliteration, we must call
3479
 
    // transliterate to finish off any pending partial matches that
3480
 
    // were waiting for more input.
3481
 
    t.finishTransliteration(rsource, index);
3482
 
    log.append(" => ").append(rsource);
3483
 
 
3484
 
    expectAux(t.getID() + ":Keyboard", log,
3485
 
              rsource == expectedResult,
3486
 
              expectedResult);
3487
 
}
3488
 
 
3489
 
    
3490
 
/**
3491
 
 * @param appendTo result is appended to this param.
3492
 
 * @param input the string being transliterated
3493
 
 * @param pos the index struct
3494
 
 */
3495
 
UnicodeString& TransliteratorTest::formatInput(UnicodeString &appendTo,
3496
 
                                               const UnicodeString& input,
3497
 
                                               const UTransPosition& pos) {
3498
 
    // Output a string of the form aaa{bbb|ccc|ddd}eee, where
3499
 
    // the {} indicate the context start and limit, and the ||
3500
 
    // indicate the start and limit.
3501
 
    if (0 <= pos.contextStart &&
3502
 
        pos.contextStart <= pos.start &&
3503
 
        pos.start <= pos.limit &&
3504
 
        pos.limit <= pos.contextLimit &&
3505
 
        pos.contextLimit <= input.length()) {
3506
 
 
3507
 
        UnicodeString a, b, c, d, e;
3508
 
        input.extractBetween(0, pos.contextStart, a);
3509
 
        input.extractBetween(pos.contextStart, pos.start, b);
3510
 
        input.extractBetween(pos.start, pos.limit, c);
3511
 
        input.extractBetween(pos.limit, pos.contextLimit, d);
3512
 
        input.extractBetween(pos.contextLimit, input.length(), e);
3513
 
        appendTo.append(a).append((UChar)123/*{*/).append(b).
3514
 
            append((UChar)PIPE).append(c).append((UChar)PIPE).append(d).
3515
 
            append((UChar)125/*}*/).append(e);
3516
 
    } else {
3517
 
        appendTo.append((UnicodeString)"INVALID UTransPosition {cs=" +
3518
 
                        pos.contextStart + ", s=" + pos.start + ", l=" +
3519
 
                        pos.limit + ", cl=" + pos.contextLimit + "} on " +
3520
 
                        input);
3521
 
    }
3522
 
    return appendTo;
3523
 
}
3524
 
 
3525
 
void TransliteratorTest::expectAux(const UnicodeString& tag,
3526
 
                                   const UnicodeString& source,
3527
 
                                   const UnicodeString& result,
3528
 
                                   const UnicodeString& expectedResult) {
3529
 
    expectAux(tag, source + " -> " + result,
3530
 
              result == expectedResult,
3531
 
              expectedResult);
3532
 
}
3533
 
 
3534
 
void TransliteratorTest::expectAux(const UnicodeString& tag,
3535
 
                                   const UnicodeString& summary, UBool pass,
3536
 
                                   const UnicodeString& expectedResult) {
3537
 
    if (pass) {
3538
 
        logln(UnicodeString("(")+tag+") " + prettify(summary));
3539
 
    } else {
3540
 
        errln(UnicodeString("FAIL: (")+tag+") "
3541
 
              + prettify(summary)
3542
 
              + ", expected " + prettify(expectedResult));
3543
 
    }
3544
 
}