Imported Upstream version 58.1
[platform/upstream/icu.git] / source / test / intltest / transapi.cpp
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /************************************************************************
4  * COPYRIGHT: 
5  * Copyright (c) 2000-2016, International Business Machines Corporation
6  * and others. All Rights Reserved.
7  ************************************************************************/
8 /************************************************************************
9 *   Date        Name        Description
10 *   1/03/2000   Madhu        Creation.
11 ************************************************************************/
12
13 #include "unicode/utypes.h"
14
15 #if !UCONFIG_NO_TRANSLITERATION
16
17 #include "ittrans.h"
18 #include "transapi.h"
19 #include "unicode/utypes.h"
20 #include "unicode/translit.h"
21 #include "unicode/unifilt.h"
22 #include "cpdtrans.h"
23 #include "cmemory.h"
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "unicode/rep.h"
28 #include "unicode/locid.h"
29 #include "unicode/uniset.h"
30
31 int32_t getInt(UnicodeString str)
32 {
33     char buffer[20];
34     int len=str.length();
35     if(len>=20) {
36         len=19;
37     }
38     str.extract(0, len, buffer, "");
39     buffer[len]=0;
40     return atoi(buffer);
41 }
42
43 //---------------------------------------------
44 // runIndexedTest
45 //---------------------------------------------
46
47 void
48 TransliteratorAPITest::runIndexedTest(int32_t index, UBool exec,
49                                       const char* &name, char* /*par*/) {
50     switch (index) {
51         TESTCASE(0,TestgetInverse);
52         TESTCASE(1,TestgetID);
53         TESTCASE(2,TestGetDisplayName);
54         TESTCASE(3,TestTransliterate1);
55         TESTCASE(4,TestTransliterate2);
56         TESTCASE(5,TestTransliterate3);
57         TESTCASE(6,TestSimpleKeyboardTransliterator);
58         TESTCASE(7,TestKeyboardTransliterator1);
59         TESTCASE(8,TestKeyboardTransliterator2);
60         TESTCASE(9,TestKeyboardTransliterator3);
61         TESTCASE(10,TestGetAdoptFilter);
62         TESTCASE(11,TestClone);
63         TESTCASE(12,TestNullTransliterator);
64         TESTCASE(13,TestRegisterUnregister);
65         TESTCASE(14,TestUnicodeFunctor);
66         default: name = ""; break;
67     }
68 }
69
70
71 void TransliteratorAPITest::TestgetID() {
72     UnicodeString trans="Latin-Greek";
73     UnicodeString ID;
74     UParseError parseError;
75     UErrorCode status = U_ZERO_ERROR;
76     Transliterator* t= Transliterator::createInstance(trans, UTRANS_FORWARD, parseError, status);
77     if(t==0 || U_FAILURE(status)){
78         dataerrln("FAIL: construction of Latin-Greek -  %s",u_errorName(status));
79         return;
80     }else{
81         ID= t->getID();
82         if(ID != trans)
83             errln("FAIL: getID returned " + ID + " instead of Latin-Greek");
84         delete t;
85     }
86     int i;
87     for (i=0; i<Transliterator::countAvailableIDs(); i++){
88         status = U_ZERO_ERROR;
89         ID = (UnicodeString) Transliterator::getAvailableID(i);
90         if(ID.indexOf("Thai")>-1){
91             continue;
92         }   
93         t = Transliterator::createInstance(ID, UTRANS_FORWARD, parseError, status);
94         if(t == 0){
95             errln("FAIL: " + ID);
96             continue;
97         }
98         if(ID != t->getID())
99             errln("FAIL: getID() returned " + t->getID() + " instead of " + ID);
100         delete t;
101     }
102     ID=(UnicodeString)Transliterator::getAvailableID(i);
103     if(ID != (UnicodeString)Transliterator::getAvailableID(0)){
104         errln("FAIL: calling getAvailableID(index > coundAvailableIDs) should make index=0\n");
105     }
106
107     Transliterator* t1=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
108     Transliterator* t2=Transliterator::createInstance("Latin-Greek", UTRANS_FORWARD, parseError, status);
109     if(t1 ==0 || t2 == 0){
110         errln("FAIL: construction");
111         return;
112     }
113     Transliterator* t3=t1->clone();
114     Transliterator* t4=t2->clone();
115
116     if(t1->getID() != t3->getID() || t2->getID() != t4->getID() || 
117        t1->getID() == t4->getID() || t2->getID() == t3->getID() || 
118        t1->getID()== t4->getID() )
119             errln("FAIL: getID or clone failed");
120
121
122     Transliterator* t5=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
123     if(t5 == 0)
124         errln("FAIL: construction");
125     else if(t1->getID() != t5->getID() || t5->getID() != t3->getID() || t1->getID() != t3->getID())
126         errln("FAIL: getID or clone failed");
127
128
129     delete t1;
130     delete t2;
131     delete t3;
132     delete t4;
133     delete t5;
134 }
135
136 void TransliteratorAPITest::TestgetInverse() {
137      UErrorCode status = U_ZERO_ERROR;
138      UParseError parseError;
139      Transliterator* t1    = Transliterator::createInstance("Katakana-Latin", UTRANS_FORWARD, parseError, status);
140      Transliterator* invt1 = Transliterator::createInstance("Latin-Katakana", UTRANS_FORWARD, parseError, status);
141      Transliterator* t2    = Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
142      Transliterator* invt2 = Transliterator::createInstance("Devanagari-Latin", UTRANS_FORWARD, parseError, status);
143      if(t1 == 0 || invt1 == 0 || t2 == 0 || invt2 == 0) {
144          dataerrln("FAIL: in instantiation - %s", u_errorName(status));
145          return;
146      }
147
148      Transliterator* inverse1=t1->createInverse(status);
149      Transliterator* inverse2=t2->createInverse(status);
150      if(inverse1->getID() != invt1->getID() || inverse2->getID() != invt2->getID()
151         || inverse1->getID() == invt2->getID() || inverse2->getID() == invt1->getID() ) 
152         errln("FAIL: getInverse() ");
153
154      UnicodeString TransID[]={
155        "Halfwidth-Fullwidth",
156        "Fullwidth-Halfwidth",
157        "Greek-Latin" ,
158        "Latin-Greek", 
159        //"Arabic-Latin", // removed in 2.0
160        //"Latin-Arabic",
161        "Katakana-Latin",
162        "Latin-Katakana",
163        //"Hebrew-Latin", // removed in 2.0
164        //"Latin-Hebrew",
165        "Cyrillic-Latin", 
166        "Latin-Cyrillic", 
167        "Devanagari-Latin", 
168        "Latin-Devanagari", 
169        "Any-Hex",
170        "Hex-Any"
171      };
172      for(uint32_t i=0; i<UPRV_LENGTHOF(TransID); i=i+2){
173          Transliterator *trans1=Transliterator::createInstance(TransID[i], UTRANS_FORWARD, parseError, status);
174          if(t1 == 0){
175            errln("FAIL: in instantiation for" + TransID[i]);
176            continue;
177          }
178          Transliterator *inver1=trans1->createInverse(status);
179          if(inver1->getID() != TransID[i+1] )
180              errln("FAIL :getInverse() for " + TransID[i] + " returned " + inver1->getID() + " instead of " + TransID[i+1]);
181          delete inver1;
182          delete trans1;
183      }
184      delete t1;
185      delete t2;
186      delete invt1;
187      delete invt2;
188      delete inverse1;
189      delete inverse2;
190
191 }
192
193 void TransliteratorAPITest::TestClone(){
194     Transliterator *t1, *t2, *t3, *t4;
195     UErrorCode status = U_ZERO_ERROR;
196     UParseError parseError;
197     t1=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
198     t2=Transliterator::createInstance("Latin-Greek", UTRANS_FORWARD, parseError, status);
199     if(t1 == 0 || t2 == 0){
200         dataerrln("FAIL: construction - %s", u_errorName(status));
201         return;
202     }
203     t3=t1->clone();
204     t4=t2->clone();
205
206     if(t1->getID() != t3->getID() || t2->getID() != t4->getID() )
207         errln("FAIL: clone or getID failed");
208     if(t1->getID()==t4->getID() || t2->getID()==t3->getID() ||  t1->getID()==t4->getID())
209         errln("FAIL: clone or getID failed");
210      
211     delete t1;
212     delete t2;
213     delete t3;
214     delete t4;
215
216 }
217
218 void TransliteratorAPITest::TestGetDisplayName() {
219     UnicodeString dispNames[]= { 
220          //ID, displayName
221         //"CurlyQuotes-StraightQuotes" ,"CurlyQuotes to StraightQuotes",
222           "Any-Hex"                ,"Any to Hex Escape",
223           "Halfwidth-Fullwidth"        ,"Halfwidth to Fullwidth" ,
224           //"Latin-Arabic"               ,"Latin to Arabic"      ,
225           "Latin-Devanagari"           ,"Latin to Devanagari"  ,
226           "Greek-Latin"                ,"Greek to Latin"       ,
227           //"Arabic-Latin"               ,"Arabic to Latin"      ,
228           "Hex-Any"                ,"Hex Escape to Any",
229           "Cyrillic-Latin"             ,"Cyrillic to Latin"    ,
230           "Latin-Greek"                ,"Latin to Greek"       ,
231           "Latin-Katakana"                 ,"Latin to Katakana"        ,
232           //"Latin-Hebrew"               ,"Latin to Hebrew"      ,
233           "Katakana-Latin"                 ,"Katakana to Latin"        
234       };
235     UnicodeString name="";
236     Transliterator* t;
237     UnicodeString message;
238     UErrorCode status = U_ZERO_ERROR;
239     UParseError parseError;
240
241 #if UCONFIG_NO_FORMATTING
242     logln("Skipping, UCONFIG_NO_FORMATTING is set\n");
243     return;
244 #else
245
246     for (uint32_t i=0; i<UPRV_LENGTHOF(dispNames); i=i+2 ) {
247         t = Transliterator::createInstance(dispNames[i+0], UTRANS_FORWARD, parseError, status);
248         if(t==0){
249              dataerrln("FAIL: construction: " + dispNames[i+0] + " - " + u_errorName(status));
250              status = U_ZERO_ERROR;
251              continue;
252         }
253         t->getDisplayName(t->getID(), name);
254         message="Display name for ID:" + t->getID();
255       //  doTest(message, name, dispNames[i+1]); //!!! This will obviously fail for any locale other than english and its children!!!
256         name=""; 
257         t->getDisplayName(t->getID(), Locale::getUS(), name);
258         message.remove();
259         message.append("Display name for on english locale ID:");
260         message.append(t->getID());
261     // message="Display name for on english locale ID:" + t->getID();
262         doTest(message, name, dispNames[i+1]);
263         name="";
264
265         delete t;
266     }
267 #endif
268
269 }
270
271 void TransliteratorAPITest::TestTransliterate1(){
272
273     UnicodeString Data[]={ 
274          //ID, input string, transliterated string
275          "Any-Hex",         "hello",    UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", "") ,
276          "Hex-Any",         UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", ""), "hello"  ,
277          "Latin-Devanagari",CharsToUnicodeString("bha\\u0304rata"), CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924") ,
278          "Latin-Devanagari",UnicodeString("kra ksha khra gra cra dya dhya",""), CharsToUnicodeString("\\u0915\\u094D\\u0930 \\u0915\\u094D\\u0936 \\u0916\\u094D\\u0930 \\u0917\\u094D\\u0930 \\u091a\\u094D\\u0930 \\u0926\\u094D\\u092F \\u0927\\u094D\\u092F") ,
279
280          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"),        CharsToUnicodeString("bh\\u0101rata"),
281      //  "Contracted-Expanded", CharsToUnicodeString("\\u00C0\\u00C1\\u0042"),               CharsToUnicodeString("\\u0041\\u0300\\u0041\\u0301\\u0042") ,
282      //  "Expanded-Contracted", CharsToUnicodeString("\\u0041\\u0300\\u0041\\u0301\\u0042"), CharsToUnicodeString("\\u00C0\\u00C1\\u0042") ,
283          //"Latin-Arabic",        "aap",                                 CharsToUnicodeString("\\u0627\\u06A4")     ,
284          //"Arabic-Latin",        CharsToUnicodeString("\\u0627\\u06A4"),                      "aap" 
285     };
286
287     UnicodeString gotResult;
288     UnicodeString temp;
289     UnicodeString message;
290     Transliterator* t;
291     logln("Testing transliterate");
292     UErrorCode status = U_ZERO_ERROR;
293     UParseError parseError;
294
295     for(uint32_t i=0;i<UPRV_LENGTHOF(Data); i=i+3){
296         t=Transliterator::createInstance(Data[i+0], UTRANS_FORWARD, parseError, status);
297         if(t==0){
298             dataerrln("FAIL: construction: " + Data[i+0] + " Error: "  + u_errorName(status));
299             dataerrln("PreContext: " + prettify(parseError.preContext) + " PostContext: " + prettify( parseError.postContext) );
300             status = U_ZERO_ERROR;
301             continue;
302         }
303         gotResult = Data[i+1];
304         t->transliterate(gotResult);
305         message=t->getID() + "->transliterate(UnicodeString, UnicodeString) for\n\t Source:" + prettify(Data[i+1]);
306         doTest(message, gotResult, Data[i+2]);
307
308         //doubt here
309         temp=Data[i+1];
310         t->transliterate(temp);
311         message.remove();
312         message.append(t->getID());
313         message.append("->transliterate(Replaceable) for \n\tSource:");
314         message.append(Data[i][1]);
315         doTest(message, temp, Data[i+2]);
316
317         callEverything(t, __LINE__);
318         delete t;
319     }
320 }
321
322 void TransliteratorAPITest::TestTransliterate2(){
323      //testing tranliterate(String text, int start, int limit, StringBuffer result)
324    UnicodeString Data2[]={
325          //ID, input string, start, limit, transliterated string
326          "Any-Hex",         "hello! How are you?",  "0", "5", UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F", ""), UnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F! How are you?", "") ,
327          "Any-Hex",         "hello! How are you?",  "7", "12", UnicodeString("\\u0048\\u006F\\u0077\\u0020\\u0061", ""), UnicodeString("hello! \\u0048\\u006F\\u0077\\u0020\\u0061re you?", ""),
328          "Hex-Any",         CharsToUnicodeString("\\u0068\\u0065\\u006C\\u006C\\u006F\\u0021\\u0020"), "0", "5",  "hello", "hello! "  ,
329        //  "Contracted-Expanded", CharsToUnicodeString("\\u00C0\\u00C1\\u0042"),        "1", "2",  CharsToUnicodeString("\\u0041\\u0301"), CharsToUnicodeString("\\u00C0\\u0041\\u0301\\u0042") ,
330          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"), "0", "1",  "bha", CharsToUnicodeString("bha\\u093E\\u0930\\u0924") ,
331          "Devanagari-Latin",    CharsToUnicodeString("\\u092D\\u093E\\u0930\\u0924"), "1", "2",  CharsToUnicodeString("\\u0314\\u0101"), CharsToUnicodeString("\\u092D\\u0314\\u0101\\u0930\\u0924")  
332
333     };
334     logln("\n   Testing transliterate(String, int, int, StringBuffer)");
335     Transliterator* t;
336     UnicodeString gotResBuf;
337     UnicodeString temp;
338     int32_t start, limit;
339     UErrorCode status = U_ZERO_ERROR;
340     UParseError parseError;
341
342     for(uint32_t i=0; i<UPRV_LENGTHOF(Data2); i=i+6){
343         t=Transliterator::createInstance(Data2[i+0], UTRANS_FORWARD, parseError, status);
344         if(t==0){
345             dataerrln("FAIL: construction: " + prettify(Data2[i+0]) + " - " + u_errorName(status));
346             continue;
347         }
348         start=getInt(Data2[i+2]);
349         limit=getInt(Data2[i+3]);
350         Data2[i+1].extractBetween(start, limit, gotResBuf);
351         t->transliterate(gotResBuf);
352         //  errln("FAIL: calling transliterate on " + t->getID());
353         doTest(t->getID() + ".transliterate(UnicodeString, int32_t, int32_t, UnicodeString):(" + start + "," + limit + ")  for \n\t source: " + prettify(Data2[i+1]), gotResBuf, Data2[i+4]);
354
355         temp=Data2[i+1];
356         t->transliterate(temp, start, limit);
357         doTest(t->getID() + ".transliterate(Replaceable, int32_t, int32_t, ):(" + start + "," + limit + ")  for \n\t source: " + prettify(Data2[i+1]), temp, Data2[i+5]);
358         status = U_ZERO_ERROR;
359         callEverything(t, __LINE__);
360         delete t;
361         t = NULL;
362     }
363
364     status = U_ZERO_ERROR;
365     logln("\n   Try calling transliterate with illegal start and limit values");
366     t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
367     if(U_FAILURE(status)) {
368       errln("Error creating transliterator %s", u_errorName(status));
369       delete t;
370       return;
371     }
372     gotResBuf = temp = "try start greater than limit";
373     t->transliterate(gotResBuf, 10, 5);
374     if(gotResBuf == temp) {
375         logln("OK: start greater than limit value handled correctly");
376     } else {
377         errln("FAIL: start greater than limit value returned" + gotResBuf);
378     }
379
380     callEverything(t, __LINE__);
381     delete t;
382
383 }
384 void TransliteratorAPITest::TestTransliterate3(){
385     UnicodeString rs="This is the replaceable String";
386     UnicodeString Data[] = {
387         "0",  "0",  "This is the replaceable String",
388         "2",  "3",  UnicodeString("Th\\u0069s is the replaceable String", ""),
389         "21", "23", UnicodeString("Th\\u0069s is the repl\\u0061\\u0063eable String", ""),
390         "14", "17", UnicodeString("Th\\u0069s is t\\u0068\\u0065\\u0020repl\\u0061\\u0063eable String", ""),
391     };
392     int start, limit;
393     UnicodeString message;
394     UParseError parseError;
395     UErrorCode status = U_ZERO_ERROR;
396     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
397     if(U_FAILURE(status)) {
398       errln("Error creating transliterator %s", u_errorName(status));
399       delete t;
400       return;
401     }
402
403     if(t == 0)
404         errln("FAIL : construction");
405     for(uint32_t i=0; i<UPRV_LENGTHOF(Data); i=i+3){
406         start=getInt(Data[i+0]);
407         limit=getInt(Data[i+1]);
408         t->transliterate(rs, start, limit);
409         message=t->getID() + ".transliterate(ReplaceableString, start, limit):("+start+","+limit+"):";
410         doTest(message, rs, Data[i+2]); 
411     }
412     delete t;
413 }
414
415 void TransliteratorAPITest::TestSimpleKeyboardTransliterator(){
416     logln("simple call to transliterate");
417     UErrorCode status=U_ZERO_ERROR;
418     UParseError parseError;
419     Transliterator* t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
420     if(t == 0) {
421         UnicodeString context;
422
423         if (parseError.preContext[0]) {
424             context += (UnicodeString)" at " + parseError.preContext;
425         }
426         if (parseError.postContext[0]) {
427             context += (UnicodeString)" | " + parseError.postContext;
428         }
429         errln((UnicodeString)"FAIL: can't create Any-Hex, " +
430               (UnicodeString)u_errorName(status) + context);
431         return;
432     }
433     UTransPosition index={19,20,20,20};
434     UnicodeString rs= "Transliterate this-''";
435     UnicodeString insertion="abc";
436     UnicodeString expected=UnicodeString("Transliterate this-'\\u0061\\u0062\\u0063'", "");
437     t->transliterate(rs, index, insertion, status);
438     if(U_FAILURE(status))
439         errln("FAIL: " + t->getID()+ ".translitere(Replaceable, int[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
440     t->finishTransliteration(rs, index);
441     UnicodeString message="transliterate";
442     doTest(message, rs, expected);
443
444     logln("try calling transliterate with invalid index values");
445     UTransPosition index1[]={
446         //START, LIMIT, CURSOR
447         {10, 10, 12, 10},   //invalid since CURSOR>LIMIT valid:-START <= CURSOR <= LIMIT
448         {17, 16, 17, 17},   //invalid since START>LIMIT valid:-0<=START<=LIMIT
449         {-1, 16, 14, 16},   //invalid since START<0
450         {3,  50, 2,  50}    //invalid since LIMIT>text.length()
451     };
452     for(uint32_t i=0; i<UPRV_LENGTHOF(index1); i++){
453         status=U_ZERO_ERROR;
454         t->transliterate(rs, index1[i], insertion, status);
455         if(status == U_ILLEGAL_ARGUMENT_ERROR)
456             logln("OK: invalid index values handled correctly");
457         else
458             errln("FAIL: invalid index values didn't throw U_ILLEGAL_ARGUMENT_ERROR throw" + (UnicodeString)u_errorName(status));
459     }
460
461     delete t;
462 }
463 void TransliteratorAPITest::TestKeyboardTransliterator1(){
464     UnicodeString Data[]={
465         //insertion, buffer
466         "a",   UnicodeString("\\u0061", "")                                           ,
467         "bbb", UnicodeString("\\u0061\\u0062\\u0062\\u0062", "")                      ,
468         "ca",  UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061", "")        ,
469         " ",   UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061\\u0020", "") ,
470         "",    UnicodeString("\\u0061\\u0062\\u0062\\u0062\\u0063\\u0061\\u0020", "")   ,
471
472         "a",   UnicodeString("\\u0061", "")                                           ,
473         "b",   UnicodeString("\\u0061\\u0062", "")                                    ,
474         "z",   UnicodeString("\\u0061\\u0062\\u007A", "")                             ,
475         "",    UnicodeString("\\u0061\\u0062\\u007A", "")                              
476
477     };
478     UParseError parseError;
479     UErrorCode status = U_ZERO_ERROR;
480     Transliterator* t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
481     if(U_FAILURE(status)) {
482       errln("Error creating transliterator %s", u_errorName(status));
483       delete t;
484       return;
485     }
486     //keyboardAux(t, Data);
487     UTransPosition index={0, 0, 0, 0};
488     UnicodeString s;
489     uint32_t i;
490     logln("Testing transliterate(Replaceable, int32_t, UnicodeString, UErrorCode)");
491     for (i=0; i<10; i=i+2) {
492        UnicodeString log;
493        if (Data[i+0] != "") {
494            log = s + " + " + Data[i+0] + " -> ";
495            t->transliterate(s, index, Data[i+0], status);
496            if(U_FAILURE(status)){
497                errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
498            continue;
499            }
500        }else {
501            log = s + " => ";
502            t->finishTransliteration(s, index);
503        }
504        // Show the start index '{' and the cursor '|'
505        displayOutput(s, Data[i+1], log, index);
506            
507     }
508     
509     s="";
510     status=U_ZERO_ERROR;
511     index.contextStart = index.contextLimit = index.start = index.limit = 0;
512     logln("Testing transliterate(Replaceable, int32_t, UChar, UErrorCode)");
513     for(i=10; i<UPRV_LENGTHOF(Data); i=i+2){
514         UnicodeString log;
515          if (Data[i+0] != "") {
516            log = s + " + " + Data[i+0] + " -> ";
517            UChar c=Data[i+0].charAt(0);
518            t->transliterate(s, index, c, status);
519            if(U_FAILURE(status))
520                errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UChar, UErrorCode)-->" + (UnicodeString)u_errorName(status));
521                continue;
522          }else {
523            log = s + " => ";
524            t->finishTransliteration(s, index);
525          }
526         // Show the start index '{' and the cursor '|'
527         displayOutput(s, Data[i+1], log, index); 
528     }
529
530     delete t;
531 }
532
533 void TransliteratorAPITest::TestKeyboardTransliterator2(){
534     UnicodeString Data[]={
535         //insertion, buffer, index[START], index[LIMIT], index[CURSOR]
536         //data for Any-Hex
537         "abc",    UnicodeString("Initial String: add-\\u0061\\u0062\\u0063-", ""),                     "19", "20", "20",
538         "a",      UnicodeString("In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""),        "2",  "3",  "2" ,
539         "b",      UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0",  "0",  "0" ,
540         "",       UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0",  "0",  "0" ,
541         //data for Latin-Devanagiri
542         CharsToUnicodeString("a\\u0304"),     CharsToUnicodeString("Hindi -\\u0906-"),                            "6", "7", "6",
543         CharsToUnicodeString("ma\\u0304"),    CharsToUnicodeString("Hindi -\\u0906\\u092E\\u093E-"),              "7", "8", "7",
544         CharsToUnicodeString("ra\\u0304"),    CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2",
545         CharsToUnicodeString(""),       CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2"
546         //data for contracted-Expanded
547      //   CharsToUnicodeString("\\u00C1"), CharsToUnicodeString("Ad\\u0041\\u0301d here:"),             "1",  "2",  "1" ,
548      //   CharsToUnicodeString("\\u00C0"), CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
549      //   "",     CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
550     };
551     Transliterator *t;
552     UnicodeString rs;
553     UnicodeString dataStr;
554     logln("Testing transliterate(Replaceable, int32_t, UnicodeString, UErrorCode)");       
555     UErrorCode status = U_ZERO_ERROR;
556     UParseError parseError;
557     rs="Initial String: add--";
558     t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
559     if(t == 0)
560         dataerrln("FAIL : construction - %s", u_errorName(status));
561     else {
562         keyboardAux(t, Data, rs, 0, 20);
563         delete t;
564     }
565
566     rs="Hindi --";
567     t=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
568     if(t == 0)
569         dataerrln("FAIL : construction - %s", u_errorName(status));
570     else
571         keyboardAux(t, Data, rs, 20, 40);
572
573
574   //  rs="Add here:";
575  //   t=Transliterator::createInstance("Contracted-Expanded");
576  //   keyboardAux(t, Data, rs, 35, 55);
577
578
579     delete t;
580 }
581
582 void TransliteratorAPITest::TestKeyboardTransliterator3(){
583     UnicodeString s="This is the main string";
584     UnicodeString Data[] = {
585         "0", "0", "0",  "This is the main string",
586         "1", "3", "2",  UnicodeString("Th\\u0069s is the main string", ""),
587         "20", "21", "20",  UnicodeString("Th\\u0069s is the mai\\u006E string", "")
588     };
589
590     UErrorCode status=U_ZERO_ERROR;
591     UParseError parseError;
592     UTransPosition index={0, 0, 0, 0};
593     logln("Testing transliterate(Replaceable, int32_t, UErrorCode)");
594     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
595     if(t == 0 || U_FAILURE(status)) {
596       errln("Error creating transliterator %s", u_errorName(status));
597       delete t;
598       return;
599     }
600     for(uint32_t i=0; i<UPRV_LENGTHOF(Data); i=i+4){
601         UnicodeString log;
602         index.contextStart=getInt(Data[i+0]);
603         index.contextLimit=index.limit=getInt(Data[i+1]);
604         index.start=getInt(Data[i+2]);
605         t->transliterate(s, index, status);
606         if(U_FAILURE(status)){
607            errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UErrorCode)-->" + (UnicodeString)u_errorName(status));
608            continue;
609         }
610         t->finishTransliteration(s, index);
611         log = s + " => ";
612         // Show the start index '{' and the cursor '|'
613         displayOutput(s, Data[i+3], log, index); 
614     }
615
616     delete t;
617 }
618 void TransliteratorAPITest::TestNullTransliterator(){
619     UErrorCode status=U_ZERO_ERROR;
620     UnicodeString s("Transliterate using null transliterator");
621     Transliterator *nullTrans=Transliterator::createInstance("Any-Null", UTRANS_FORWARD, status);
622     int32_t transLimit;
623     int32_t start=0;
624     int32_t limit=s.length();
625     UnicodeString replaceable=s;
626     transLimit=nullTrans->transliterate(replaceable, start, limit);
627     if(transLimit != limit){
628         errln("ERROR: NullTransliterator->transliterate() failed");
629     }
630     doTest((UnicodeString)"nulTrans->transliterate", replaceable, s);
631     replaceable.remove();
632     replaceable.append(s);
633     UTransPosition index;
634     index.contextStart =start;
635     index.contextLimit = limit;
636     index.start = 0;
637     index.limit = limit;
638     nullTrans->finishTransliteration(replaceable, index);
639     if(index.start != limit){
640         errln("ERROR: NullTransliterator->handleTransliterate() failed");
641     }
642     doTest((UnicodeString)"NullTransliterator->handleTransliterate", replaceable, s);
643     callEverything(nullTrans, __LINE__);
644     delete nullTrans;
645
646     
647 }
648 void TransliteratorAPITest::TestRegisterUnregister(){
649    
650    UErrorCode status=U_ZERO_ERROR;
651     /* Make sure it doesn't exist */
652    if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
653       errln("FAIL: TestA-TestB already registered\n");
654       return;
655    }
656    /* Check inverse too 
657    if (Transliterator::createInstance("TestA-TestB",
658                                       (UTransDirection)UTRANS_REVERSE) != NULL) {
659       errln("FAIL: TestA-TestB inverse already registered\n");
660       return;
661    }
662    */
663    status =U_ZERO_ERROR;
664
665    /* Create it */
666    UParseError parseError;
667    Transliterator *t = Transliterator::createFromRules("TestA-TestB",
668                                                    "a<>b",
669                                                    UTRANS_FORWARD, parseError,
670                                                    status);
671    /* Register it */
672    Transliterator::registerInstance(t);
673
674    /* Now check again -- should exist now*/
675    Transliterator *s = Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status);
676    if (s == NULL) {
677       errln("FAIL: TestA-TestB not registered\n");
678       return;
679    }
680    callEverything(s, __LINE__);
681    callEverything(t, __LINE__);
682    delete s;
683    
684    /* Check inverse too
685    s = Transliterator::createInstance("TestA-TestB",
686                                       (UTransDirection)UTRANS_REVERSE);
687    if (s == NULL) {
688       errln("FAIL: TestA-TestB inverse not registered\n");
689       return;
690    }
691    delete s;
692    */
693    
694    /*unregister the instance*/
695    Transliterator::unregister("TestA-TestB");
696    /* now Make sure it doesn't exist */
697    if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
698       errln("FAIL: TestA-TestB isn't unregistered\n");
699       return;
700    }
701
702 }
703
704
705 int gTestFilter1ClassID = 0;
706 int gTestFilter2ClassID = 0;
707 int gTestFilter3ClassID = 0;
708
709 /**
710  * Used by TestFiltering().
711  */
712 class TestFilter1 : public UnicodeFilter {
713     UClassID getDynamicClassID()const { return &gTestFilter1ClassID; }
714     virtual UnicodeFunctor* clone() const {
715         return new TestFilter1(*this);
716     }
717     virtual UBool contains(UChar32 c) const {
718        if(c==0x63 || c==0x61 || c==0x43 || c==0x41)
719           return FALSE;
720        else
721           return TRUE;
722     }
723     // Stubs
724     virtual UnicodeString& toPattern(UnicodeString& result,
725                                      UBool /*escapeUnprintable*/) const {
726         return result;
727     }
728     virtual UBool matchesIndexValue(uint8_t /*v*/) const {
729         return FALSE;
730     }
731     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const {}
732 };
733 class TestFilter2 : public UnicodeFilter {
734     UClassID getDynamicClassID()const { return &gTestFilter2ClassID; }
735     virtual UnicodeFunctor* clone() const {
736         return new TestFilter2(*this);
737     }
738     virtual UBool contains(UChar32 c) const {
739         if(c==0x65 || c==0x6c)
740            return FALSE;
741         else
742            return TRUE;
743     }
744     // Stubs
745     virtual UnicodeString& toPattern(UnicodeString& result,
746                                      UBool /*escapeUnprintable*/) const {
747         return result;
748     }
749     virtual UBool matchesIndexValue(uint8_t /*v*/) const {
750         return FALSE;
751     }
752     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const {}
753 };
754 class TestFilter3 : public UnicodeFilter {
755     UClassID getDynamicClassID()const { return &gTestFilter3ClassID; }
756     virtual UnicodeFunctor* clone() const {
757         return new TestFilter3(*this);
758     }
759     virtual UBool contains(UChar32 c) const {
760         if(c==0x6f || c==0x77)
761            return FALSE;
762         else
763            return TRUE;
764     }
765     // Stubs
766     virtual UnicodeString& toPattern(UnicodeString& result,
767                                      UBool /*escapeUnprintable*/) const {
768         return result;
769     }
770     virtual UBool matchesIndexValue(uint8_t /*v*/) const {
771         return FALSE;
772     }
773     virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const {}
774 };
775
776
777 void TransliteratorAPITest::TestGetAdoptFilter(){
778     UErrorCode status = U_ZERO_ERROR;
779     UParseError parseError;
780     Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
781     if(t == 0 || U_FAILURE(status)) {
782         errln("Error creating transliterator %s", u_errorName(status));
783         delete t;
784         return;
785     }
786     const UnicodeFilter *u=t->getFilter();
787     if(u != NULL){
788         errln("FAIL: getFilter failed. Didn't return null when the transliterator used no filtering");
789         delete t;
790         return;
791     }
792
793     UnicodeString got, temp, message;
794     UnicodeString data="ABCabcbbCBa";
795     temp = data;
796     t->transliterate(temp);
797     t->adoptFilter(new TestFilter1);
798
799     got = data;
800     t->transliterate(got);
801     UnicodeString exp=UnicodeString("A\\u0042Ca\\u0062c\\u0062\\u0062C\\u0042a", "");
802     message="transliteration after adoptFilter(a,A,c,C) ";
803     doTest(message, got, exp);
804          
805     logln("Testing round trip");
806     t->adoptFilter((UnicodeFilter*)u);
807     if(t->getFilter() == NULL)
808        logln("OK: adoptFilter and getFilter round trip worked");
809     else
810        errln("FAIL: adoptFilter or getFilter round trip failed");  
811
812     got = data;
813     t->transliterate(got);
814     exp=UnicodeString("\\u0041\\u0042\\u0043\\u0061\\u0062\\u0063\\u0062\\u0062\\u0043\\u0042\\u0061", "");
815     message="transliteration after adopting null filter";
816     doTest(message, got, exp);
817     message="adoptFilter round trip"; 
818     doTest("adoptFilter round trip", got, temp);
819
820     t->adoptFilter(new TestFilter2);
821     callEverything(t, __LINE__);
822     data="heelloe";
823     exp=UnicodeString("\\u0068eell\\u006Fe", "");
824     got = data;
825     t->transliterate(got);
826     message="transliteration using (e,l) filter";
827     doTest("transliteration using (e,l) filter", got, exp);
828
829     data="are well";
830     exp=UnicodeString("\\u0061\\u0072e\\u0020\\u0077ell", "");
831     got = data;
832     t->transliterate(got);
833     doTest(message, got, exp);
834
835     t->adoptFilter(new TestFilter3);
836     data="ho, wow!";
837     exp=UnicodeString("\\u0068o\\u002C\\u0020wow\\u0021", "");
838     got = data;
839     t->transliterate(got);
840     message="transliteration using (o,w) filter";
841     doTest("transliteration using (o,w) filter", got, exp);
842
843     data="owl";
844     exp=UnicodeString("ow\\u006C", "");
845     got = data;
846     t->transliterate(got);
847     doTest("transliteration using (o,w) filter", got, exp);
848
849     delete t;
850
851 }
852
853
854
855 void TransliteratorAPITest::keyboardAux(Transliterator *t, UnicodeString DATA[], UnicodeString& s, int32_t begin, int32_t end) {
856     UTransPosition index={0, 0, 0, 0};
857     UErrorCode status=U_ZERO_ERROR;
858     for (int32_t i=begin; i<end; i=i+5) {
859         UnicodeString log;
860         if (DATA[i+0] != "") {
861              log = s + " + " + DATA[i] + " -> ";
862              index.contextStart=getInt(DATA[i+2]);
863              index.contextLimit=index.limit=getInt(DATA[i+3]);
864              index.start=getInt(DATA[i+4]);
865              t->transliterate(s, index, DATA[i+0], status);
866              if(U_FAILURE(status)){
867                  errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
868              continue;
869              }
870            log = s + " => ";
871            t->finishTransliteration(s, index);
872         }
873          // Show the start index '{' and the cursor '|'
874       displayOutput(s, DATA[i+1], log, index);
875         
876     }
877 }
878
879 void TransliteratorAPITest::displayOutput(const UnicodeString& got, const UnicodeString& expected, UnicodeString& log, UTransPosition& index){
880  // Show the start index '{' and the cursor '|'
881     UnicodeString a, b, c, d, e;
882     got.extractBetween(0, index.contextStart, a);
883     got.extractBetween(index.contextStart, index.start, b);
884     got.extractBetween(index.start, index.limit, c);
885     got.extractBetween(index.limit, index.contextLimit, d);
886     got.extractBetween(index.contextLimit, got.length(), e);
887     log.append(a).
888         append((UChar)0x7b/*{*/).
889         append(b).
890         append((UChar)0x7c/*|*/).
891         append(c).
892         append((UChar)0x7c).
893         append(d).
894         append((UChar)0x7d/*}*/).
895         append(e);
896     if (got == expected) 
897         logln("OK:" + prettify(log));
898     else 
899         errln("FAIL: " + prettify(log)  + ", expected " + prettify(expected));
900 }
901
902
903 /*Internal Functions used*/
904 void TransliteratorAPITest::doTest(const UnicodeString& message, const UnicodeString& result, const UnicodeString& expected){
905     if (prettify(result) == prettify(expected)) 
906         logln((UnicodeString)"Ok: " + prettify(message) + " passed \"" + prettify(expected) + "\"");
907     else 
908         dataerrln((UnicodeString)"FAIL:" + message + " failed  Got-->" + prettify(result)+ ", Expected--> " + prettify(expected) );
909 }
910
911
912 //
913 //  callEverything    call all of the const (non-destructive) methods on a
914 //                    transliterator, just to verify that they don't fail in some
915 //                    destructive way.
916 //
917 #define CEASSERT(a) {if (!(a)) { \
918 errln("FAIL at line %d from line %d: %s", __LINE__, line, #a);  return; }}
919
920 void TransliteratorAPITest::callEverything(const Transliterator *tr, int line) {
921     Transliterator *clonedTR = tr->clone();
922     CEASSERT(clonedTR != NULL);
923
924     int32_t  maxcl = tr->getMaximumContextLength();
925     CEASSERT(clonedTR->getMaximumContextLength() == maxcl);
926
927     UnicodeString id;
928     UnicodeString clonedId;
929     id = tr->getID();
930     clonedId = clonedTR->getID();
931     CEASSERT(id == clonedId);
932
933     const UnicodeFilter *filter = tr->getFilter();
934     const UnicodeFilter *clonedFilter = clonedTR->getFilter();
935     if (filter == NULL || clonedFilter == NULL) {
936         // If one filter is NULL they better both be NULL.
937         CEASSERT(filter == clonedFilter);
938     } else {
939         CEASSERT(filter != clonedFilter);
940     }
941
942     UnicodeString rules;
943     UnicodeString clonedRules;
944     rules = tr->toRules(rules, FALSE);
945     clonedRules = clonedTR->toRules(clonedRules, FALSE);
946     CEASSERT(rules == clonedRules);
947
948     UnicodeSet sourceSet;
949     UnicodeSet clonedSourceSet;
950     tr->getSourceSet(sourceSet);
951     clonedTR->getSourceSet(clonedSourceSet);
952     CEASSERT(clonedSourceSet == sourceSet);
953
954     UnicodeSet targetSet;
955     UnicodeSet clonedTargetSet;
956     tr->getTargetSet(targetSet);
957     clonedTR->getTargetSet(clonedTargetSet);
958     CEASSERT(targetSet == clonedTargetSet);
959
960     UClassID classID = tr->getDynamicClassID();
961     CEASSERT(classID == clonedTR->getDynamicClassID());
962     CEASSERT(classID != 0);
963
964     delete clonedTR;
965 }
966
967 static const int MyUnicodeFunctorTestClassID = 0;
968 class MyUnicodeFunctorTestClass : public UnicodeFunctor {
969 public:
970     virtual UnicodeFunctor* clone() const {return NULL;}
971     static UClassID getStaticClassID(void) {return (UClassID)&MyUnicodeFunctorTestClassID;}
972     virtual UClassID getDynamicClassID(void) const {return getStaticClassID();};
973     virtual void setData(const TransliterationRuleData*) {}
974 };
975
976 void TransliteratorAPITest::TestUnicodeFunctor() {
977     MyUnicodeFunctorTestClass myClass;
978     if (myClass.toMatcher() != NULL) {
979         errln("FAIL: UnicodeFunctor::toMatcher did not return NULL");
980     }
981     if (myClass.toReplacer() != NULL) {
982         errln("FAIL: UnicodeFunctor::toReplacer did not return NULL");
983     }
984 }
985
986
987 #endif /* #if !UCONFIG_NO_TRANSLITERATION */