1 // © 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
getInt(UnicodeString str)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
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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
TestgetID()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
TestgetInverse()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
TestClone()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
TestGetDisplayName()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
TestTransliterate1()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
TestTransliterate2()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 }
TestTransliterate3()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
TestSimpleKeyboardTransliterator()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 }
TestKeyboardTransliterator1()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 }
523 } else {
524 log = s + " => ";
525 t->finishTransliteration(s, index);
526 }
527 // Show the start index '{' and the cursor '|'
528 displayOutput(s, Data[i+1], log, index);
529 }
530
531 delete t;
532 }
533
TestKeyboardTransliterator2()534 void TransliteratorAPITest::TestKeyboardTransliterator2(){
535 UnicodeString Data[]={
536 //insertion, buffer, index[START], index[LIMIT], index[CURSOR]
537 //data for Any-Hex
538 "abc", UnicodeString("Initial String: add-\\u0061\\u0062\\u0063-", ""), "19", "20", "20",
539 "a", UnicodeString("In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "2", "3", "2" ,
540 "b", UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0", "0", "0" ,
541 "", UnicodeString("\\u0062In\\u0069\\u0061tial String: add-\\u0061\\u0062\\u0063-", ""), "0", "0", "0" ,
542 //data for Latin-Devanagiri
543 CharsToUnicodeString("a\\u0304"), CharsToUnicodeString("Hindi -\\u0906-"), "6", "7", "6",
544 CharsToUnicodeString("ma\\u0304"), CharsToUnicodeString("Hindi -\\u0906\\u092E\\u093E-"), "7", "8", "7",
545 CharsToUnicodeString("ra\\u0304"), CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2",
546 CharsToUnicodeString(""), CharsToUnicodeString("Hi\\u0930\\u093Endi -\\u0906\\u092E\\u093E-"),"1", "2", "2"
547 //data for contracted-Expanded
548 // CharsToUnicodeString("\\u00C1"), CharsToUnicodeString("Ad\\u0041\\u0301d here:"), "1", "2", "1" ,
549 // CharsToUnicodeString("\\u00C0"), CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
550 // "", CharsToUnicodeString("Ad\\u0041\\u0301d here:\\u0041\\u0300"), "11", "11", "11",
551 };
552 Transliterator *t;
553 UnicodeString rs;
554 UnicodeString dataStr;
555 logln("Testing transliterate(Replaceable, int32_t, UnicodeString, UErrorCode)");
556 UErrorCode status = U_ZERO_ERROR;
557 UParseError parseError;
558 rs="Initial String: add--";
559 t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
560 if(t == 0)
561 dataerrln("FAIL : construction - %s", u_errorName(status));
562 else {
563 keyboardAux(t, Data, rs, 0, 20);
564 delete t;
565 }
566
567 rs="Hindi --";
568 t=Transliterator::createInstance("Latin-Devanagari", UTRANS_FORWARD, parseError, status);
569 if(t == 0)
570 dataerrln("FAIL : construction - %s", u_errorName(status));
571 else
572 keyboardAux(t, Data, rs, 20, 40);
573
574
575 // rs="Add here:";
576 // t=Transliterator::createInstance("Contracted-Expanded");
577 // keyboardAux(t, Data, rs, 35, 55);
578
579
580 delete t;
581 }
582
TestKeyboardTransliterator3()583 void TransliteratorAPITest::TestKeyboardTransliterator3(){
584 UnicodeString s="This is the main string";
585 UnicodeString Data[] = {
586 "0", "0", "0", "This is the main string",
587 "1", "3", "2", UnicodeString("Th\\u0069s is the main string", ""),
588 "20", "21", "20", UnicodeString("Th\\u0069s is the mai\\u006E string", "")
589 };
590
591 UErrorCode status=U_ZERO_ERROR;
592 UParseError parseError;
593 UTransPosition index={0, 0, 0, 0};
594 logln("Testing transliterate(Replaceable, int32_t, UErrorCode)");
595 Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
596 if(t == 0 || U_FAILURE(status)) {
597 errln("Error creating transliterator %s", u_errorName(status));
598 delete t;
599 return;
600 }
601 for(uint32_t i=0; i<UPRV_LENGTHOF(Data); i=i+4){
602 UnicodeString log;
603 index.contextStart=getInt(Data[i+0]);
604 index.contextLimit=index.limit=getInt(Data[i+1]);
605 index.start=getInt(Data[i+2]);
606 t->transliterate(s, index, status);
607 if(U_FAILURE(status)){
608 errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UErrorCode)-->" + (UnicodeString)u_errorName(status));
609 continue;
610 }
611 t->finishTransliteration(s, index);
612 log = s + " => ";
613 // Show the start index '{' and the cursor '|'
614 displayOutput(s, Data[i+3], log, index);
615 }
616
617 delete t;
618 }
TestNullTransliterator()619 void TransliteratorAPITest::TestNullTransliterator(){
620 UErrorCode status=U_ZERO_ERROR;
621 UnicodeString s("Transliterate using null transliterator");
622 Transliterator *nullTrans=Transliterator::createInstance("Any-Null", UTRANS_FORWARD, status);
623 if (!assertSuccess(WHERE, status)) {
624 return;
625 }
626 int32_t transLimit;
627 int32_t start=0;
628 int32_t limit=s.length();
629 UnicodeString replaceable=s;
630 transLimit=nullTrans->transliterate(replaceable, start, limit);
631 if(transLimit != limit){
632 errln("ERROR: NullTransliterator->transliterate() failed");
633 }
634 doTest((UnicodeString)"nulTrans->transliterate", replaceable, s);
635 replaceable.remove();
636 replaceable.append(s);
637 UTransPosition index;
638 index.contextStart =start;
639 index.contextLimit = limit;
640 index.start = 0;
641 index.limit = limit;
642 nullTrans->finishTransliteration(replaceable, index);
643 if(index.start != limit){
644 errln("ERROR: NullTransliterator->handleTransliterate() failed");
645 }
646 doTest((UnicodeString)"NullTransliterator->handleTransliterate", replaceable, s);
647 callEverything(nullTrans, __LINE__);
648 delete nullTrans;
649
650
651 }
TestRegisterUnregister()652 void TransliteratorAPITest::TestRegisterUnregister(){
653
654 UErrorCode status=U_ZERO_ERROR;
655 /* Make sure it doesn't exist */
656 if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
657 errln("FAIL: TestA-TestB already registered\n");
658 return;
659 }
660 /* Check inverse too
661 if (Transliterator::createInstance("TestA-TestB",
662 (UTransDirection)UTRANS_REVERSE) != NULL) {
663 errln("FAIL: TestA-TestB inverse already registered\n");
664 return;
665 }
666 */
667 status =U_ZERO_ERROR;
668
669 /* Create it */
670 UParseError parseError;
671 Transliterator *t = Transliterator::createFromRules("TestA-TestB",
672 "a<>b",
673 UTRANS_FORWARD, parseError,
674 status);
675 /* Register it */
676 Transliterator::registerInstance(t);
677
678 /* Now check again -- should exist now*/
679 Transliterator *s = Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status);
680 if (s == NULL) {
681 errln("FAIL: TestA-TestB not registered\n");
682 return;
683 }
684 callEverything(s, __LINE__);
685 callEverything(t, __LINE__);
686 delete s;
687
688 /* Check inverse too
689 s = Transliterator::createInstance("TestA-TestB",
690 (UTransDirection)UTRANS_REVERSE);
691 if (s == NULL) {
692 errln("FAIL: TestA-TestB inverse not registered\n");
693 return;
694 }
695 delete s;
696 */
697
698 /*unregister the instance*/
699 Transliterator::unregister("TestA-TestB");
700 /* now Make sure it doesn't exist */
701 if (Transliterator::createInstance("TestA-TestB", UTRANS_FORWARD, status) != NULL) {
702 errln("FAIL: TestA-TestB isn't unregistered\n");
703 return;
704 }
705
706 }
707
708
709 int gTestFilter1ClassID = 0;
710 int gTestFilter2ClassID = 0;
711 int gTestFilter3ClassID = 0;
712
713 /**
714 * Used by TestFiltering().
715 */
716 class TestFilter1 : public UnicodeFilter {
getDynamicClassID() const717 UClassID getDynamicClassID()const override { return &gTestFilter1ClassID; }
clone() const718 virtual TestFilter1* clone() const override {
719 return new TestFilter1(*this);
720 }
contains(UChar32 c) const721 virtual UBool contains(UChar32 c) const override {
722 if(c==0x63 || c==0x61 || c==0x43 || c==0x41)
723 return false;
724 else
725 return true;
726 }
727 // Stubs
toPattern(UnicodeString & result,UBool) const728 virtual UnicodeString& toPattern(UnicodeString& result,
729 UBool /*escapeUnprintable*/) const override {
730 return result;
731 }
matchesIndexValue(uint8_t) const732 virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
733 return false;
734 }
addMatchSetTo(UnicodeSet &) const735 virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
736 };
737 class TestFilter2 : public UnicodeFilter {
getDynamicClassID() const738 UClassID getDynamicClassID() const override { return &gTestFilter2ClassID; }
clone() const739 virtual TestFilter2* clone() const override {
740 return new TestFilter2(*this);
741 }
contains(UChar32 c) const742 virtual UBool contains(UChar32 c) const override {
743 if(c==0x65 || c==0x6c)
744 return false;
745 else
746 return true;
747 }
748 // Stubs
toPattern(UnicodeString & result,UBool) const749 virtual UnicodeString& toPattern(UnicodeString& result,
750 UBool /*escapeUnprintable*/) const override {
751 return result;
752 }
matchesIndexValue(uint8_t) const753 virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
754 return false;
755 }
addMatchSetTo(UnicodeSet &) const756 virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
757 };
758 class TestFilter3 : public UnicodeFilter {
getDynamicClassID() const759 UClassID getDynamicClassID() const override { return &gTestFilter3ClassID; }
clone() const760 virtual TestFilter3* clone() const override {
761 return new TestFilter3(*this);
762 }
contains(UChar32 c) const763 virtual UBool contains(UChar32 c) const override {
764 if(c==0x6f || c==0x77)
765 return false;
766 else
767 return true;
768 }
769 // Stubs
toPattern(UnicodeString & result,UBool) const770 virtual UnicodeString& toPattern(UnicodeString& result,
771 UBool /*escapeUnprintable*/) const override {
772 return result;
773 }
matchesIndexValue(uint8_t) const774 virtual UBool matchesIndexValue(uint8_t /*v*/) const override {
775 return false;
776 }
addMatchSetTo(UnicodeSet &) const777 virtual void addMatchSetTo(UnicodeSet& /*toUnionTo*/) const override {}
778 };
779
780
TestGetAdoptFilter()781 void TransliteratorAPITest::TestGetAdoptFilter(){
782 UErrorCode status = U_ZERO_ERROR;
783 UParseError parseError;
784 Transliterator *t=Transliterator::createInstance("Any-Hex", UTRANS_FORWARD, parseError, status);
785 if(t == 0 || U_FAILURE(status)) {
786 errln("Error creating transliterator %s", u_errorName(status));
787 delete t;
788 return;
789 }
790 const UnicodeFilter *u=t->getFilter();
791 if(u != NULL){
792 errln("FAIL: getFilter failed. Didn't return null when the transliterator used no filtering");
793 delete t;
794 return;
795 }
796
797 UnicodeString got, temp, message;
798 UnicodeString data="ABCabcbbCBa";
799 temp = data;
800 t->transliterate(temp);
801 t->adoptFilter(new TestFilter1);
802
803 got = data;
804 t->transliterate(got);
805 UnicodeString exp=UnicodeString("A\\u0042Ca\\u0062c\\u0062\\u0062C\\u0042a", "");
806 message="transliteration after adoptFilter(a,A,c,C) ";
807 doTest(message, got, exp);
808
809 logln("Testing round trip");
810 t->adoptFilter((UnicodeFilter*)u);
811 if(t->getFilter() == NULL)
812 logln("OK: adoptFilter and getFilter round trip worked");
813 else
814 errln("FAIL: adoptFilter or getFilter round trip failed");
815
816 got = data;
817 t->transliterate(got);
818 exp=UnicodeString("\\u0041\\u0042\\u0043\\u0061\\u0062\\u0063\\u0062\\u0062\\u0043\\u0042\\u0061", "");
819 message="transliteration after adopting null filter";
820 doTest(message, got, exp);
821 message="adoptFilter round trip";
822 doTest("adoptFilter round trip", got, temp);
823
824 t->adoptFilter(new TestFilter2);
825 callEverything(t, __LINE__);
826 data="heelloe";
827 exp=UnicodeString("\\u0068eell\\u006Fe", "");
828 got = data;
829 t->transliterate(got);
830 message="transliteration using (e,l) filter";
831 doTest("transliteration using (e,l) filter", got, exp);
832
833 data="are well";
834 exp=UnicodeString("\\u0061\\u0072e\\u0020\\u0077ell", "");
835 got = data;
836 t->transliterate(got);
837 doTest(message, got, exp);
838
839 t->adoptFilter(new TestFilter3);
840 data="ho, wow!";
841 exp=UnicodeString("\\u0068o\\u002C\\u0020wow\\u0021", "");
842 got = data;
843 t->transliterate(got);
844 message="transliteration using (o,w) filter";
845 doTest("transliteration using (o,w) filter", got, exp);
846
847 data="owl";
848 exp=UnicodeString("ow\\u006C", "");
849 got = data;
850 t->transliterate(got);
851 doTest("transliteration using (o,w) filter", got, exp);
852
853 delete t;
854
855 }
856
857
858
keyboardAux(Transliterator * t,UnicodeString DATA[],UnicodeString & s,int32_t begin,int32_t end)859 void TransliteratorAPITest::keyboardAux(Transliterator *t, UnicodeString DATA[], UnicodeString& s, int32_t begin, int32_t end) {
860 UTransPosition index={0, 0, 0, 0};
861 UErrorCode status=U_ZERO_ERROR;
862 for (int32_t i=begin; i<end; i=i+5) {
863 UnicodeString log;
864 if (DATA[i+0] != "") {
865 log = s + " + " + DATA[i] + " -> ";
866 index.contextStart=getInt(DATA[i+2]);
867 index.contextLimit=index.limit=getInt(DATA[i+3]);
868 index.start=getInt(DATA[i+4]);
869 t->transliterate(s, index, DATA[i+0], status);
870 if(U_FAILURE(status)){
871 errln("FAIL: " + t->getID()+ ".transliterate(Replaceable, int32_t[], UnicodeString, UErrorCode)-->" + (UnicodeString)u_errorName(status));
872 continue;
873 }
874 log = s + " => ";
875 t->finishTransliteration(s, index);
876 }
877 // Show the start index '{' and the cursor '|'
878 displayOutput(s, DATA[i+1], log, index);
879
880 }
881 }
882
displayOutput(const UnicodeString & got,const UnicodeString & expected,UnicodeString & log,UTransPosition & index)883 void TransliteratorAPITest::displayOutput(const UnicodeString& got, const UnicodeString& expected, UnicodeString& log, UTransPosition& index){
884 // Show the start index '{' and the cursor '|'
885 UnicodeString a, b, c, d, e;
886 got.extractBetween(0, index.contextStart, a);
887 got.extractBetween(index.contextStart, index.start, b);
888 got.extractBetween(index.start, index.limit, c);
889 got.extractBetween(index.limit, index.contextLimit, d);
890 got.extractBetween(index.contextLimit, got.length(), e);
891 log.append(a).
892 append((UChar)0x7b/*{*/).
893 append(b).
894 append((UChar)0x7c/*|*/).
895 append(c).
896 append((UChar)0x7c).
897 append(d).
898 append((UChar)0x7d/*}*/).
899 append(e);
900 if (got == expected)
901 logln("OK:" + prettify(log));
902 else
903 errln("FAIL: " + prettify(log) + ", expected " + prettify(expected));
904 }
905
906
907 /*Internal Functions used*/
doTest(const UnicodeString & message,const UnicodeString & result,const UnicodeString & expected)908 void TransliteratorAPITest::doTest(const UnicodeString& message, const UnicodeString& result, const UnicodeString& expected){
909 if (prettify(result) == prettify(expected))
910 logln((UnicodeString)"Ok: " + prettify(message) + " passed \"" + prettify(expected) + "\"");
911 else
912 dataerrln((UnicodeString)"FAIL:" + message + " failed Got-->" + prettify(result)+ ", Expected--> " + prettify(expected) );
913 }
914
915
916 //
917 // callEverything call all of the const (non-destructive) methods on a
918 // transliterator, just to verify that they don't fail in some
919 // destructive way.
920 //
921 #define CEASSERT(a) UPRV_BLOCK_MACRO_BEGIN { \
922 if (!(a)) { \
923 errln("FAIL at line %d from line %d: %s", __LINE__, line, #a); \
924 return; \
925 } \
926 } UPRV_BLOCK_MACRO_END
927
callEverything(const Transliterator * tr,int line)928 void TransliteratorAPITest::callEverything(const Transliterator *tr, int line) {
929 Transliterator *clonedTR = tr->clone();
930 CEASSERT(clonedTR != NULL);
931
932 int32_t maxcl = tr->getMaximumContextLength();
933 CEASSERT(clonedTR->getMaximumContextLength() == maxcl);
934
935 UnicodeString id;
936 UnicodeString clonedId;
937 id = tr->getID();
938 clonedId = clonedTR->getID();
939 CEASSERT(id == clonedId);
940
941 const UnicodeFilter *filter = tr->getFilter();
942 const UnicodeFilter *clonedFilter = clonedTR->getFilter();
943 if (filter == NULL || clonedFilter == NULL) {
944 // If one filter is NULL they better both be NULL.
945 CEASSERT(filter == clonedFilter);
946 } else {
947 CEASSERT(filter != clonedFilter);
948 }
949
950 UnicodeString rules;
951 UnicodeString clonedRules;
952 rules = tr->toRules(rules, false);
953 clonedRules = clonedTR->toRules(clonedRules, false);
954 CEASSERT(rules == clonedRules);
955
956 UnicodeSet sourceSet;
957 UnicodeSet clonedSourceSet;
958 tr->getSourceSet(sourceSet);
959 clonedTR->getSourceSet(clonedSourceSet);
960 CEASSERT(clonedSourceSet == sourceSet);
961
962 UnicodeSet targetSet;
963 UnicodeSet clonedTargetSet;
964 tr->getTargetSet(targetSet);
965 clonedTR->getTargetSet(clonedTargetSet);
966 CEASSERT(targetSet == clonedTargetSet);
967
968 UClassID classID = tr->getDynamicClassID();
969 CEASSERT(classID == clonedTR->getDynamicClassID());
970 CEASSERT(classID != 0);
971
972 delete clonedTR;
973 }
974
975 static const int MyUnicodeFunctorTestClassID = 0;
976 class MyUnicodeFunctorTestClass : public UnicodeFunctor {
977 public:
clone() const978 virtual UnicodeFunctor* clone() const override {return NULL;}
getStaticClassID(void)979 static UClassID getStaticClassID(void) {return (UClassID)&MyUnicodeFunctorTestClassID;}
getDynamicClassID(void) const980 virtual UClassID getDynamicClassID(void) const override {return getStaticClassID();}
setData(const TransliterationRuleData *)981 virtual void setData(const TransliterationRuleData*) override {}
982 };
983
TestUnicodeFunctor()984 void TransliteratorAPITest::TestUnicodeFunctor() {
985 MyUnicodeFunctorTestClass myClass;
986 if (myClass.toMatcher() != NULL) {
987 errln("FAIL: UnicodeFunctor::toMatcher did not return NULL");
988 }
989 if (myClass.toReplacer() != NULL) {
990 errln("FAIL: UnicodeFunctor::toReplacer did not return NULL");
991 }
992 }
993
994
995 #endif /* #if !UCONFIG_NO_TRANSLITERATION */
996