1/********************************************************************
2 * Copyright (c) 2001-2009, International Business Machines
3 * Corporation and others. All Rights Reserved.
4 *********************************************************************
5 *   This test program is intended for testing error conditions of the
6 *   transliterator APIs to make sure the exceptions are raised where
7 *   necessary.
8 *
9 *   Date        Name        Description
10 *   11/14/2001  hshih       Creation.
11 *
12 ********************************************************************/
13
14#include "unicode/utypes.h"
15
16#if !UCONFIG_NO_TRANSLITERATION
17
18#include "ittrans.h"
19#include "trnserr.h"
20#include "unicode/utypes.h"
21#include "unicode/translit.h"
22#include "unicode/uniset.h"
23#include "unicode/unifilt.h"
24#include "cpdtrans.h"
25#include <string.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include "unicode/rep.h"
29#include "unicode/locid.h"
30
31//---------------------------------------------
32// runIndexedTest
33//---------------------------------------------
34
35void
36TransliteratorErrorTest::runIndexedTest(int32_t index, UBool exec,
37                                      const char* &name, char* /*par*/) {
38    switch (index) {
39        TESTCASE(0,TestTransliteratorErrors);
40        TESTCASE(1, TestUnicodeSetErrors);
41        TESTCASE(2, TestRBTErrors);
42        TESTCASE(3, TestCoverage);
43        //TESTCASE(3, TestUniToHexErrors);
44        //TESTCASE(4, TestHexToUniErrors);
45        // TODO: Add a subclass to test clone().
46        default: name = ""; break;
47    }
48}
49
50
51void TransliteratorErrorTest::TestTransliteratorErrors() {
52    UnicodeString trans="Latin-Greek";
53    UnicodeString bogusID="LATINGREEK-GREEKLATIN";
54    UnicodeString newID="Bogus-Latin";
55    UnicodeString newIDRules="zzz > Z; f <> ph";
56    UnicodeString bogusRules="a } [b-g m-p ";
57    UParseError parseError;
58    UErrorCode status = U_ZERO_ERROR;
59    UnicodeString testString="A quick fox jumped over the lazy dog.";
60    UnicodeString insertString="cats and dogs";
61    int32_t stoppedAt = 0, len;
62    UTransPosition pos;
63
64    Transliterator* t= Transliterator::createInstance(trans, UTRANS_FORWARD, parseError, status);
65    if(t==0 || U_FAILURE(status)){
66        dataerrln("FAIL: construction of Latin-Greek - %s", u_errorName(status));
67        return;
68    }
69    pos.contextLimit = 0;
70    pos.contextStart = 0;
71    pos.limit = 0;
72    pos.start = 0;
73    len = testString.length();
74    stoppedAt = t->transliterate(testString, 0, 100);
75    if (stoppedAt != -1) {
76        errln("FAIL: Out of bounds check failed (1).");
77    } else if (testString.length() != len) {
78        testString="A quick fox jumped over the lazy dog.";
79        errln("FAIL: Transliterate fails and the target string was modified.");
80    }
81    stoppedAt = t->transliterate(testString, 100, testString.length()-1);
82    if (stoppedAt != -1)
83        errln("FAIL: Out of bounds check failed (2).");
84    else if (testString.length() != len) {
85        testString="A quick fox jumped over the lazy dog.";
86        errln("FAIL: Transliterate fails and the target string was modified.");
87    }
88    pos.start = 100;
89    pos.limit = testString.length();
90    t->transliterate(testString, pos, status);
91    if (U_SUCCESS(status)) {
92        errln("FAIL: Start offset is out of bounds, error not reported.\n");
93    }
94    status = U_ZERO_ERROR;
95    pos.limit = 100;
96    pos.start = 0;
97    t->transliterate(testString, pos, status);
98    if (U_SUCCESS(status)) {
99        errln("FAIL: Limit offset is out of bounds, error not reported.\n");
100    }
101    status = U_ZERO_ERROR;
102    len = pos.contextLimit = testString.length();
103    pos.contextStart = 0;
104    pos.limit = len - 1;
105    pos.start = 5;
106    t->transliterate(testString, pos, insertString, status);
107    if (len == pos.limit) {
108        errln("FAIL: Test insertion with string: the transliteration position limit didn't change as expected.");
109        if (U_SUCCESS(status)) {
110            errln("FAIL: Error code wasn't set either.");
111        }
112    }
113    status = U_ZERO_ERROR;
114    pos.contextStart = 0;
115    pos.contextLimit = testString.length();
116    pos.limit = testString.length() -1;
117    pos.start = 5;
118    t->transliterate(testString, pos, (UChar32)0x0061, status);
119    if (len == pos.limit) {
120        errln("FAIL: Test insertion with character: the transliteration position limit didn't change as expected.");
121        if (U_SUCCESS(status)) {
122            errln("FAIL: Error code wasn't set either.");
123        }
124    }
125    status = U_ZERO_ERROR;
126    len = pos.limit = testString.length();
127    pos.contextStart = 0;
128    pos.contextLimit = testString.length() - 1;
129    pos.start = 5;
130    t->transliterate(testString, pos, insertString, status);
131    if (U_SUCCESS(status)) {
132        errln("FAIL: Out of bounds check failed (3).");
133        if (testString.length() != len)
134            errln("FAIL: The input string was modified though the offsets were out of bounds.");
135    }
136    Transliterator* t1= Transliterator::createInstance(bogusID, UTRANS_FORWARD, parseError, status);
137    if(t1!=0 || U_SUCCESS(status)){
138        delete t1;
139        errln("FAIL: construction of bogus ID \"LATINGREEK-GREEKLATIN\"");
140    }
141    status = U_ZERO_ERROR;
142    Transliterator* t2 = Transliterator::createFromRules(newID, newIDRules, UTRANS_FORWARD, parseError, status);
143    if (U_SUCCESS(status)) {
144        Transliterator* t3 = t2->createInverse(status);
145        if (U_SUCCESS(status)) {
146            delete t3;
147            errln("FAIL: The newID transliterator was not registered so createInverse should fail.");
148        } else {
149            delete t3;
150        }
151    }
152    status = U_ZERO_ERROR;
153    Transliterator* t4 = Transliterator::createFromRules(newID, bogusRules, UTRANS_FORWARD, parseError, status);
154    if (t4 != NULL || U_SUCCESS(status)) {
155        errln("FAIL: The rules is malformed but error was not reported.");
156        if (parseError.offset != -1) {
157            errln("FAIL: The parse error offset isn't set correctly when fails.");
158        } else if (parseError.postContext[0] == 0 || parseError.preContext[0] == 0) {
159            errln("FAIL: The parse error pre/post context isn't reset properly.");
160        }
161        delete t4;
162    }
163    delete t;
164    delete t2;
165}
166
167void TransliteratorErrorTest::TestUnicodeSetErrors() {
168    UnicodeString badPattern="[[:L:]-[0x0300-0x0400]";
169    UnicodeSet set;
170    UErrorCode status = U_ZERO_ERROR;
171    UnicodeString result;
172
173    if (!set.isEmpty()) {
174        errln("FAIL: The default ctor of UnicodeSet created a non-empty object.");
175    }
176    set.applyPattern(badPattern, status);
177    if (U_SUCCESS(status)) {
178        errln("FAIL: Applied a bad pattern to the UnicodeSet object okay.");
179    }
180    status = U_ZERO_ERROR;
181    UnicodeSet *set1 = new UnicodeSet(badPattern, status);
182    if (U_SUCCESS(status)) {
183        errln("FAIL: Created a UnicodeSet based on bad patterns.");
184    }
185    delete set1;
186}
187
188//void TransliteratorErrorTest::TestUniToHexErrors() {
189//    UErrorCode status = U_ZERO_ERROR;
190//    Transliterator *t = new UnicodeToHexTransliterator("", TRUE, NULL, status);
191//    if (U_SUCCESS(status)) {
192//        errln("FAIL: Created a UnicodeToHexTransliterator with an empty pattern.");
193//    }
194//    delete t;
195//
196//    status = U_ZERO_ERROR;
197//    t = new UnicodeToHexTransliterator("\\x", TRUE, NULL, status);
198//    if (U_SUCCESS(status)) {
199//        errln("FAIL: Created a UnicodeToHexTransliterator with a bad pattern.");
200//    }
201//    delete t;
202//
203//    status = U_ZERO_ERROR;
204//    t = new UnicodeToHexTransliterator();
205//    ((UnicodeToHexTransliterator*)t)->applyPattern("\\x", status);
206//    if (U_SUCCESS(status)) {
207//        errln("FAIL: UnicodeToHexTransliterator::applyPattern succeeded with a bad pattern.");
208//    }
209//    delete t;
210//}
211
212void TransliteratorErrorTest::TestRBTErrors() {
213
214    UnicodeString rules="ab>y";
215    UnicodeString id="MyRandom-YReverse";
216    //UnicodeString goodPattern="[[:L:]&[\\u0000-\\uFFFF]]"; /* all BMP letters */
217    UErrorCode status = U_ZERO_ERROR;
218    UParseError parseErr;
219    /*UnicodeSet *set = new UnicodeSet(goodPattern, status);
220    if (U_FAILURE(status)) {
221        errln("FAIL: Was not able to create a good UnicodeSet based on valid patterns.");
222        return;
223    }*/
224    Transliterator *t = Transliterator::createFromRules(id, rules, UTRANS_REVERSE, parseErr, status);
225    if (U_FAILURE(status)) {
226        errln("FAIL: Was not able to create a good RBT to test registration.");
227        //delete set;
228        return;
229    }
230    Transliterator::registerInstance(t);
231    Transliterator::unregister(id);
232    status = U_ZERO_ERROR;
233    Transliterator* t1= Transliterator::createInstance(id, UTRANS_REVERSE, parseErr, status);
234    if(U_SUCCESS(status)){
235        delete t1;
236        errln("FAIL: construction of unregistered ID failed.");
237    }
238}
239
240//void TransliteratorErrorTest::TestHexToUniErrors() {
241//    UErrorCode status = U_ZERO_ERROR;
242//    Transliterator *t = new HexToUnicodeTransliterator("", NULL, status);
243//    if (U_FAILURE(status)) {
244//        errln("FAIL: Could not create a HexToUnicodeTransliterator with an empty pattern.");
245//    }
246//    delete t;
247//    status = U_ZERO_ERROR;
248//    t = new HexToUnicodeTransliterator("\\x", NULL, status);
249//    if (U_SUCCESS(status)) {
250//        errln("FAIL: Created a HexToUnicodeTransliterator with a bad pattern.");
251//    }
252//    delete t;
253//    status = U_ZERO_ERROR;
254//    t = new HexToUnicodeTransliterator();
255//    ((HexToUnicodeTransliterator*)t)->applyPattern("\\x", status);
256//    if (U_SUCCESS(status)) {
257//        errln("FAIL: HexToUnicodeTransliterator::applyPattern succeeded with a bad pattern.");
258//    }
259//    delete t;
260//}
261
262class StubTransliterator: public Transliterator{
263public:
264    StubTransliterator(): Transliterator(UNICODE_STRING_SIMPLE("Any-Null"), 0) {}
265    virtual void handleTransliterate(Replaceable& ,UTransPosition& offsets,UBool) const {
266        offsets.start = offsets.limit;
267    }
268
269    virtual UClassID getDynamicClassID() const{
270        static char classID = 0;
271        return (UClassID)&classID;
272    }
273};
274
275void TransliteratorErrorTest::TestCoverage() {
276    StubTransliterator stub;
277
278    if (stub.clone() != NULL){
279        errln("FAIL: default Transliterator::clone() should return NULL");
280    }
281}
282
283#endif /* #if !UCONFIG_NO_TRANSLITERATION */
284