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