1/******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2009, 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 29U_CDECL_BEGIN 30static void U_CALLCONV deleteSeqElement(void *elem) { 31 delete((SeqElement *)elem); 32} 33U_CDECL_END 34 35DataDrivenCollatorTest::DataDrivenCollatorTest() 36: seq(StringCharacterIterator("")), 37status(U_ZERO_ERROR), 38sequences(status) 39{ 40 driver = TestDataModule::getTestDataModule("DataDrivenCollationTest", *this, status); 41 sequences.setDeleter(deleteSeqElement); 42 UCA = (RuleBasedCollator*)Collator::createInstance("root", status); 43} 44 45DataDrivenCollatorTest::~DataDrivenCollatorTest() 46{ 47 delete driver; 48 delete UCA; 49} 50 51void 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 83UBool 84DataDrivenCollatorTest::setTestSequence(const UnicodeString &setSequence, SeqElement &el) { 85 seq.setText(setSequence); 86 return getNextInSequence(el); 87} 88 89// Parses the sequence to be tested 90UBool 91DataDrivenCollatorTest::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 148void 149DataDrivenCollatorTest::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 167void 168DataDrivenCollatorTest::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); 200 return; 201 } 202 } else { 203 errln("No collator definition!"); 204 } 205 } 206 207 int32_t cloneSize = 0; 208 uint8_t* cloneBuf = NULL; 209 RuleBasedCollator* clone = NULL; 210 if(col != NULL){ 211 RuleBasedCollator* rbc = (RuleBasedCollator*)col; 212 cloneSize = rbc->cloneBinary(NULL, 0, intStatus); 213 intStatus = U_ZERO_ERROR; 214 cloneBuf = (uint8_t*) malloc(cloneSize); 215 cloneSize = rbc->cloneBinary(cloneBuf, cloneSize, intStatus); 216 clone = new RuleBasedCollator(cloneBuf, cloneSize, UCA, intStatus); 217 if(U_FAILURE(intStatus)){ 218 errln("Could not clone the RuleBasedCollator. Error: %s", u_errorName(intStatus)); 219 intStatus= U_ZERO_ERROR; 220 } 221 // get attributes 222 testSetting = settings->getString("Arguments", intStatus); 223 if(U_SUCCESS(intStatus)) { 224 logln("Arguments: "+testSetting); 225 argLen = testSetting.length(); 226 arguments = testSetting.getBuffer(); 227 processArguments(col, arguments, argLen); 228 if(clone != NULL){ 229 processArguments(clone, arguments, argLen); 230 } 231 if(U_FAILURE(status)) { 232 errln("Couldn't process arguments"); 233 break; 234 } 235 } else { 236 intStatus = U_ZERO_ERROR; 237 } 238 // Start the processing 239 while(testData->nextCase(currentCase, status)) { 240 UnicodeString sequence = currentCase->getString("sequence", status); 241 if(U_SUCCESS(status)) { 242 processSequence(col, sequence); 243 if(clone != NULL){ 244 processSequence(clone, sequence); 245 } 246 } 247 } 248 } else { 249 errln("Couldn't instantiate a collator!"); 250 } 251 delete clone; 252 free(cloneBuf); 253 delete col; 254 col = NULL; 255 } 256} 257 258 259void 260DataDrivenCollatorTest::processSequence(Collator* col, const UnicodeString &sequence) { 261 Collator::EComparisonResult relation = Collator::EQUAL; 262 UBool hasNext; 263 SeqElement *source = NULL; 264 SeqElement *target = NULL; 265 int32_t j = 0; 266 267 sequences.removeAllElements(); 268 269 target = new SeqElement(); 270 271 setTestSequence(sequence, *target); 272 sequences.addElement(target, status); 273 274 do { 275 relation = Collator::EQUAL; 276 target = new SeqElement(); 277 hasNext = getNextInSequence(*target); 278 for(j = sequences.size(); j > 0; j--) { 279 source = (SeqElement *)sequences.elementAt(j-1); 280 if(relation == Collator::EQUAL && source->relation != Collator::EQUAL) { 281 relation = source->relation; 282 } 283 doTest(col, source->source, target->source, relation); 284 } 285 sequences.addElement(target, status); 286 source = target; 287 } while(hasNext); 288} 289 290#endif /* #if !UCONFIG_NO_COLLATION */ 291