• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2005, 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
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
deleteSeqElement(void * elem)30 static void U_CALLCONV deleteSeqElement(void *elem) {
31   delete((SeqElement *)elem);
32 }
33 U_CDECL_END
34 
DataDrivenCollatorTest()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 
~DataDrivenCollatorTest()45 DataDrivenCollatorTest::~DataDrivenCollatorTest()
46 {
47   delete driver;
48   delete UCA;
49 }
50 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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     errln("collate/DataDrivenTest data not initialized!");
77     name = "";
78   }
79 
80 
81 }
82 
83 UBool
setTestSequence(const UnicodeString & setSequence,SeqElement & el)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
getNextInSequence(SeqElement & el)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
processArguments(Collator * col,const UChar * start,int32_t optLen)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
processTest(TestData * testData)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
processSequence(Collator * col,const UnicodeString & sequence)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