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