Home | History | Annotate | Download | only in intltest
      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