Home | History | Annotate | Download | only in intltest
      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 
     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);
    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 
    259 void
    260 DataDrivenCollatorTest::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