1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2010, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 /** 8 * IntlTestCollator is the medium level test class for everything in the directory "collate". 9 */ 10 11 /*********************************************************************** 12 * Modification history 13 * Date Name Description 14 * 02/14/2001 synwee Compare with cintltst and commented away tests 15 * that are not run. 16 ***********************************************************************/ 17 18 #include "unicode/utypes.h" 19 20 #if !UCONFIG_NO_COLLATION && !UCONFIG_NO_FILE_IO 21 22 #include "unicode/uchar.h" 23 #include "unicode/tstdtmod.h" 24 #include "cstring.h" 25 #include "ucol_tok.h" 26 #include "tscoll.h" 27 #include "dadrcoll.h" 28 29 U_CDECL_BEGIN 30 static void U_CALLCONV deleteSeqElement(void *elem) { 31 delete((SeqElement *)elem); 32 } 33 U_CDECL_END 34 35 DataDrivenCollatorTest::DataDrivenCollatorTest() 36 : seq(StringCharacterIterator("")), 37 status(U_ZERO_ERROR), 38 sequences(status) 39 { 40 driver = TestDataModule::getTestDataModule("DataDrivenCollationTest", *this, status); 41 sequences.setDeleter(deleteSeqElement); 42 UCA = (RuleBasedCollator*)Collator::createInstance("root", status); 43 } 44 45 DataDrivenCollatorTest::~DataDrivenCollatorTest() 46 { 47 delete driver; 48 delete UCA; 49 } 50 51 void DataDrivenCollatorTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */) 52 { 53 if(driver != NULL) { 54 if (exec) 55 { 56 logln("TestSuite Collator: "); 57 } 58 const DataMap *info = NULL; 59 TestData *testData = driver->createTestData(index, status); 60 if(U_SUCCESS(status)) { 61 name = testData->getName(); 62 if(testData->getInfo(info, status)) { 63 log(info->getString("Description", status)); 64 } 65 if(exec) { 66 log(name); 67 logln("---"); 68 logln(""); 69 processTest(testData); 70 } 71 delete testData; 72 } else { 73 name = ""; 74 } 75 } else { 76 dataerrln("collate/DataDrivenTest data not initialized!"); 77 name = ""; 78 } 79 80 81 } 82 83 UBool 84 DataDrivenCollatorTest::setTestSequence(const UnicodeString &setSequence, SeqElement &el) { 85 seq.setText(setSequence); 86 return getNextInSequence(el); 87 } 88 89 // Parses the sequence to be tested 90 UBool 91 DataDrivenCollatorTest::getNextInSequence(SeqElement &el) { 92 el.source.truncate(0); 93 UBool quoted = FALSE; 94 UBool quotedsingle = FALSE; 95 UChar32 currChar = 0; 96 97 while(currChar != CharacterIterator::DONE) { 98 currChar= seq.next32PostInc(); 99 if(!quoted) { 100 if(u_isWhitespace(currChar)) { 101 continue; 102 } 103 switch(currChar) { 104 case CharacterIterator::DONE: 105 break; 106 case 0x003C /* < */: 107 el.relation = Collator::LESS; 108 currChar = CharacterIterator::DONE; 109 break; 110 case 0x003D /* = */: 111 el.relation = Collator::EQUAL; 112 currChar = CharacterIterator::DONE; 113 break; 114 case 0x003E /* > */: 115 el.relation = Collator::GREATER; 116 currChar = CharacterIterator::DONE; 117 break; 118 case 0x0027 /* ' */: /* very basic quoting */ 119 quoted = TRUE; 120 quotedsingle = FALSE; 121 break; 122 case 0x005c /* \ */: /* single quote */ 123 quoted = TRUE; 124 quotedsingle = TRUE; 125 break; 126 default: 127 el.source.append(currChar); 128 } 129 } else { 130 if(currChar == CharacterIterator::DONE) { 131 status = U_ILLEGAL_ARGUMENT_ERROR; 132 errln("Quote in sequence not closed!"); 133 return FALSE; 134 } else if(currChar == 0x0027) { 135 quoted = FALSE; 136 } else { 137 el.source.append(currChar); 138 } 139 if(quotedsingle) { 140 quoted = FALSE; 141 } 142 } 143 } 144 return seq.hasNext(); 145 } 146 147 // Reads the options string and sets appropriate attributes in collator 148 void 149 DataDrivenCollatorTest::processArguments(Collator *col, const UChar *start, int32_t optLen) { 150 const UChar *end = start+optLen; 151 UColAttribute attrib; 152 UColAttributeValue value; 153 154 if(optLen == 0) { 155 return; 156 } 157 158 start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status); 159 while(start != NULL) { 160 if(U_SUCCESS(status)) { 161 col->setAttribute(attrib, value, status); 162 } 163 start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status); 164 } 165 } 166 167 void 168 DataDrivenCollatorTest::processTest(TestData *testData) { 169 Collator *col = NULL; 170 const UChar *arguments = NULL; 171 int32_t argLen = 0; 172 const DataMap *settings = NULL; 173 const DataMap *currentCase = NULL; 174 UErrorCode intStatus = U_ZERO_ERROR; 175 UnicodeString testSetting; 176 while(testData->nextSettings(settings, status)) { 177 intStatus = U_ZERO_ERROR; 178 // try to get a locale 179 testSetting = settings->getString("TestLocale", intStatus); 180 if(U_SUCCESS(intStatus)) { 181 char localeName[256]; 182 testSetting.extract(0, testSetting.length(), localeName, ""); 183 col = Collator::createInstance(localeName, status); 184 if(U_SUCCESS(status)) { 185 logln("Testing collator for locale "+testSetting); 186 } else { 187 errln("Unable to instantiate collator for locale "+testSetting); 188 return; 189 } 190 } else { 191 // if no locale, try from rules 192 intStatus = U_ZERO_ERROR; 193 testSetting = settings->getString("Rules", intStatus); 194 if(U_SUCCESS(intStatus)) { 195 col = new RuleBasedCollator(testSetting, status); 196 if(U_SUCCESS(status)) { 197 logln("Testing collator for rules "+testSetting); 198 } else { 199 errln("Unable to instantiate collator for rules "+testSetting+" - "+u_errorName(status)); 200 return; 201 } 202 } else { 203 errln("No collator definition!"); 204 return; 205 } 206 } 207 208 int32_t cloneSize = 0; 209 uint8_t* cloneBuf = NULL; 210 RuleBasedCollator* clone = NULL; 211 if(col != NULL){ 212 RuleBasedCollator* rbc = (RuleBasedCollator*)col; 213 cloneSize = rbc->cloneBinary(NULL, 0, intStatus); 214 intStatus = U_ZERO_ERROR; 215 cloneBuf = (uint8_t*) malloc(cloneSize); 216 cloneSize = rbc->cloneBinary(cloneBuf, cloneSize, intStatus); 217 clone = new RuleBasedCollator(cloneBuf, cloneSize, UCA, intStatus); 218 if(U_FAILURE(intStatus)){ 219 errln("Could not clone the RuleBasedCollator. Error: %s", u_errorName(intStatus)); 220 intStatus= U_ZERO_ERROR; 221 } 222 // get attributes 223 testSetting = settings->getString("Arguments", intStatus); 224 if(U_SUCCESS(intStatus)) { 225 logln("Arguments: "+testSetting); 226 argLen = testSetting.length(); 227 arguments = testSetting.getBuffer(); 228 processArguments(col, arguments, argLen); 229 if(clone != NULL){ 230 processArguments(clone, arguments, argLen); 231 } 232 if(U_FAILURE(status)) { 233 errln("Couldn't process arguments"); 234 break; 235 } 236 } else { 237 intStatus = U_ZERO_ERROR; 238 } 239 // Start the processing 240 while(testData->nextCase(currentCase, status)) { 241 UnicodeString sequence = currentCase->getString("sequence", status); 242 if(U_SUCCESS(status)) { 243 processSequence(col, sequence); 244 if(clone != NULL){ 245 processSequence(clone, sequence); 246 } 247 } 248 } 249 } else { 250 errln("Couldn't instantiate a collator!"); 251 } 252 delete clone; 253 free(cloneBuf); 254 delete col; 255 col = NULL; 256 } 257 } 258 259 260 void 261 DataDrivenCollatorTest::processSequence(Collator* col, const UnicodeString &sequence) { 262 Collator::EComparisonResult relation = Collator::EQUAL; 263 UBool hasNext; 264 SeqElement *source = NULL; 265 SeqElement *target = NULL; 266 int32_t j = 0; 267 268 sequences.removeAllElements(); 269 270 target = new SeqElement(); 271 272 setTestSequence(sequence, *target); 273 sequences.addElement(target, status); 274 275 do { 276 relation = Collator::EQUAL; 277 target = new SeqElement(); 278 hasNext = getNextInSequence(*target); 279 for(j = sequences.size(); j > 0; j--) { 280 source = (SeqElement *)sequences.elementAt(j-1); 281 if(relation == Collator::EQUAL && source->relation != Collator::EQUAL) { 282 relation = source->relation; 283 } 284 doTest(col, source->source, target->source, relation); 285 } 286 sequences.addElement(target, status); 287 source = target; 288 } while(hasNext); 289 } 290 291 #endif /* #if !UCONFIG_NO_COLLATION */ 292