]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/tscoll.cpp
ICU-400.38.tar.gz
[apple/icu.git] / icuSources / test / intltest / tscoll.cpp
CommitLineData
b75a7d8f
A
1/********************************************************************
2 * COPYRIGHT:
46f4442e 3 * Copyright (c) 1997-2008, International Business Machines Corporation and
b75a7d8f
A
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"
374ca955 23#include "unicode/ustring.h"
b75a7d8f
A
24
25#include "dadrcoll.h"
26
27#include "encoll.h"
28#include "frcoll.h"
29#include "decoll.h"
b75a7d8f
A
30#include "escoll.h"
31#include "ficoll.h"
32#include "jacoll.h"
33#include "trcoll.h"
34#include "allcoll.h"
35#include "g7coll.h"
36#include "mnkytst.h"
37#include "apicoll.h"
38#include "regcoll.h"
39#include "currcoll.h"
40#include "itercoll.h"
b75a7d8f
A
41#include "tstnorm.h"
42#include "normconf.h"
43#include "thcoll.h"
44#include "srchtest.h"
46f4442e 45#include "ssearch.h"
b75a7d8f
A
46#include "cntabcol.h"
47#include "lcukocol.h"
48#include "ucaconf.h"
49#include "svccoll.h"
374ca955 50#include "cmemory.h"
46f4442e
A
51//#include "rndmcoll.h"
52
53// Set to 1 to test offsets in backAndForth()
54#define TEST_OFFSETS 0
374ca955
A
55
56#define TESTCLASS(n,classname) \
57 case n: \
58 name = #classname; \
59 if (exec) { \
60 logln(#classname "---"); \
61 logln(""); \
62 classname t; \
63 callTest(t, par); \
64 } \
65 break
b75a7d8f
A
66
67void IntlTestCollator::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
68{
374ca955 69 if (exec) {
b75a7d8f
A
70 logln("TestSuite Collator: ");
71 }
72
374ca955
A
73 switch (index) {
74 TESTCLASS(0, CollationEnglishTest);
75 TESTCLASS(1, CollationFrenchTest);
76 TESTCLASS(2, CollationGermanTest);
77 TESTCLASS(3, CollationSpanishTest);
78 TESTCLASS(4, CollationKanaTest);
79 TESTCLASS(5, CollationTurkishTest);
80 TESTCLASS(6, CollationDummyTest);
81 TESTCLASS(7, G7CollationTest);
82 TESTCLASS(8, CollationMonkeyTest);
83 TESTCLASS(9, CollationAPITest);
84 TESTCLASS(10, CollationRegressionTest);
85 TESTCLASS(11, CollationCurrencyTest);
86 TESTCLASS(12, CollationIteratorTest);
87 TESTCLASS(13, CollationThaiTest);
88 TESTCLASS(14, LotusCollationKoreanTest);
89 TESTCLASS(15, StringSearchTest);
90 TESTCLASS(16, ContractionTableTest);
91 TESTCLASS(17, DataDrivenCollatorTest);
92 TESTCLASS(18, UCAConformanceTest);
93 TESTCLASS(19, CollationServiceTest);
374ca955 94 TESTCLASS(20, CollationFinnishTest); // removed by weiv - we have changed Finnish collation
46f4442e
A
95 //TESTCLASS(21, RandomCollatorTest); // See ticket 5747 about reenabling this test.
96 TESTCLASS(21, SSearchTest);
73c04bcf 97
374ca955 98 default: name = ""; break;
b75a7d8f
A
99 }
100}
101
102UCollationResult
103IntlTestCollator::compareUsingPartials(UCollator *coll, const UChar source[], int32_t sLen, const UChar target[], int32_t tLen, int32_t pieceSize, UErrorCode &status) {
104 int32_t partialSKResult = 0;
105 uint8_t sBuf[512], tBuf[512];
106 UCharIterator sIter, tIter;
107 uint32_t sState[2], tState[2];
108 int32_t sSize = pieceSize, tSize = pieceSize;
109 int32_t i = 0;
110 status = U_ZERO_ERROR;
111 sState[0] = 0; sState[1] = 0;
112 tState[0] = 0; tState[1] = 0;
113 while(sSize == pieceSize && tSize == pieceSize && partialSKResult == 0) {
114 uiter_setString(&sIter, source, sLen);
115 uiter_setString(&tIter, target, tLen);
116 sSize = ucol_nextSortKeyPart(coll, &sIter, sState, sBuf, pieceSize, &status);
117 tSize = ucol_nextSortKeyPart(coll, &tIter, tState, tBuf, pieceSize, &status);
118
119 if(sState[0] != 0 || tState[0] != 0) {
120 log("State != 0 : %08X %08X\n", sState[0], tState[0]);
121 }
122 log("%i ", i++);
123
124 partialSKResult = memcmp(sBuf, tBuf, pieceSize);
125 }
126
127 if(partialSKResult < 0) {
128 return UCOL_LESS;
129 } else if(partialSKResult > 0) {
130 return UCOL_GREATER;
131 } else {
132 return UCOL_EQUAL;
133 }
134}
135
136void
137IntlTestCollator::doTestVariant(Collator* col, const UnicodeString &source, const UnicodeString &target, Collator::EComparisonResult result)
138{
139 UErrorCode status = U_ZERO_ERROR;
140
141 UCollator *myCollation = (UCollator *)((RuleBasedCollator *)col)->getUCollator();
142
143 Collator::EComparisonResult compareResult = col->compare(source, target);
144
145 CollationKey srckey, tgtkey;
146 col->getCollationKey(source, srckey, status);
147 col->getCollationKey(target, tgtkey, status);
148 if (U_FAILURE(status)){
149 errln("Creation of collation keys failed\n");
150 }
151 Collator::EComparisonResult keyResult = srckey.compareTo(tgtkey);
152
153 reportCResult(source, target, srckey, tgtkey, compareResult, keyResult, result, result);
154
155 UColAttributeValue norm = ucol_getAttribute(myCollation, UCOL_NORMALIZATION_MODE, &status);
156
157 int32_t sLen = source.length(), tLen = target.length();
158 const UChar* src = source.getBuffer();
159 const UChar* trg = target.getBuffer();
160 UCollationResult compareResultIter = (UCollationResult)result;
161
46f4442e 162 {
b75a7d8f
A
163 UCharIterator sIter, tIter;
164 uiter_setString(&sIter, src, sLen);
165 uiter_setString(&tIter, trg, tLen);
166 compareResultIter = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
167 if(compareResultIter != (UCollationResult)result) {
168 errln("Different result for iterative comparison "+source+" "+target);
169 }
170 }
171 /* convert the strings to UTF-8 and do try comparing with char iterator */
172 if(!quick) { /*!QUICK*/
173 char utf8Source[256], utf8Target[256];
174 int32_t utf8SourceLen = 0, utf8TargetLen = 0;
175 u_strToUTF8(utf8Source, 256, &utf8SourceLen, src, sLen, &status);
176 if(U_FAILURE(status)) { /* probably buffer is not big enough */
177 log("Src UTF-8 buffer too small! Will not compare!\n");
178 } else {
179 u_strToUTF8(utf8Target, 256, &utf8TargetLen, trg, tLen, &status);
180 if(U_SUCCESS(status)) { /* probably buffer is not big enough */
181 UCollationResult compareResultUTF8 = (UCollationResult)result, compareResultUTF8Norm = (UCollationResult)result;
182 UCharIterator sIter, tIter;
183 /*log_verbose("Strings converted to UTF-8:%s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));*/
184 uiter_setUTF8(&sIter, utf8Source, utf8SourceLen);
185 uiter_setUTF8(&tIter, utf8Target, utf8TargetLen);
186 /*uiter_setString(&sIter, source, sLen);
187 uiter_setString(&tIter, target, tLen);*/
188 compareResultUTF8 = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
189 ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
190 sIter.move(&sIter, 0, UITER_START);
191 tIter.move(&tIter, 0, UITER_START);
192 compareResultUTF8Norm = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
193 ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
194 if(compareResultUTF8 != compareResultIter) {
195 errln("different results in iterative comparison for UTF-16 and UTF-8 encoded strings. "+source+", "+target);
196 }
197 if(compareResultUTF8 != compareResultUTF8Norm) {
198 errln("different results in iterative when normalization is turned on with UTF-8 strings. "+source+", "+target);
199 }
200 } else {
201 log("Target UTF-8 buffer too small! Did not compare!\n");
202 }
203 if(U_FAILURE(status)) {
204 log("UTF-8 strcoll failed! Ignoring result\n");
205 }
206 }
207 }
208
209 /* testing the partial sortkeys */
46f4442e 210 { /*!QUICK*/
b75a7d8f
A
211 int32_t partialSizes[] = { 3, 1, 2, 4, 8, 20, 80 }; /* just size 3 in the quick mode */
212 int32_t partialSizesSize = 1;
213 if(!quick) {
214 partialSizesSize = 7;
215 }
216 int32_t i = 0;
217 log("partial sortkey test piecesize=");
218 for(i = 0; i < partialSizesSize; i++) {
219 UCollationResult partialSKResult = (UCollationResult)result, partialNormalizedSKResult = (UCollationResult)result;
220 log("%i ", partialSizes[i]);
221
222 partialSKResult = compareUsingPartials(myCollation, src, sLen, trg, tLen, partialSizes[i], status);
223 if(partialSKResult != (UCollationResult)result) {
224 errln("Partial sortkey comparison returned wrong result: "+source+", "+target+" (size "+partialSizes[i]+")");
225 }
226
227 if(norm != UCOL_ON && !quick) {
228 log("N ");
229 ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
230 partialNormalizedSKResult = compareUsingPartials(myCollation, src, sLen, trg, tLen, partialSizes[i], status);
231 ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
232 if(partialSKResult != partialNormalizedSKResult) {
233 errln("Partial sortkey comparison gets different result when normalization is on: "+source+", "+target+" (size "+partialSizes[i]+")");
234 }
235 }
236 }
237 log("\n");
238 }
239/*
240 if (compareResult != result) {
241 errln("String comparison failed in variant test\n");
242 }
243 if (keyResult != result) {
244 errln("Collation key comparison failed in variant test\n");
245 }
246*/
247}
248
249void
250IntlTestCollator::doTest(Collator* col, const UChar *source, const UChar *target, Collator::EComparisonResult result) {
251 doTest(col, UnicodeString(source), UnicodeString(target), result);
252}
253
254void
255IntlTestCollator::doTest(Collator* col, const UnicodeString &source, const UnicodeString &target, Collator::EComparisonResult result)
256{
257 if(col) {
258 doTestVariant(col, source, target, result);
259 if(result == Collator::LESS) {
260 doTestVariant(col, target, source, Collator::GREATER);
261 } else if (result == Collator::GREATER) {
262 doTestVariant(col, target, source, Collator::LESS);
263 }
264
265 UErrorCode status = U_ZERO_ERROR;
266 CollationElementIterator* c = ((RuleBasedCollator *)col)->createCollationElementIterator( source );
267 logln("Testing iterating source: "+source);
268 backAndForth(*c);
269 c->setText(target, status);
270 logln("Testing iterating target: "+target);
271 backAndForth(*c);
272 delete c;
273 }
274}
275
276
277// used for collation result reporting, defined here for convenience
278// (maybe moved later)
279void
280IntlTestCollator::reportCResult( const UnicodeString &source, const UnicodeString &target,
281 CollationKey &sourceKey, CollationKey &targetKey,
282 Collator::EComparisonResult compareResult,
283 Collator::EComparisonResult keyResult,
284 Collator::EComparisonResult incResult,
285 Collator::EComparisonResult expectedResult )
286{
287 if (expectedResult < -1 || expectedResult > 1)
288 {
289 errln("***** invalid call to reportCResult ****");
290 return;
291 }
292
293 UBool ok1 = (compareResult == expectedResult);
294 UBool ok2 = (keyResult == expectedResult);
295 UBool ok3 = (incResult == expectedResult);
296
297
298 if (ok1 && ok2 && ok3 && !verbose) {
299 // Keep non-verbose, passing tests fast
300 return;
301 } else {
302 UnicodeString msg1(ok1 ? "Ok: compare(" : "FAIL: compare(");
303 UnicodeString msg2(", "), msg3(") returned "), msg4("; expected ");
304 UnicodeString prettySource, prettyTarget, sExpect, sResult;
305
306 IntlTest::prettify(source, prettySource);
307 IntlTest::prettify(target, prettyTarget);
308 appendCompareResult(compareResult, sResult);
309 appendCompareResult(expectedResult, sExpect);
310
311 if (ok1) {
312 logln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult);
313 } else {
314 errln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult + msg4 + sExpect);
315 }
316
317 msg1 = UnicodeString(ok2 ? "Ok: key(" : "FAIL: key(");
318 msg2 = ").compareTo(key(";
319 msg3 = ")) returned ";
320
321 appendCompareResult(keyResult, sResult);
322
323 if (ok2) {
324 logln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult);
325 } else {
326 errln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult + msg4 + sExpect);
327
328 msg1 = " ";
329 msg2 = " vs. ";
330
331 prettify(sourceKey, prettySource);
332 prettify(targetKey, prettyTarget);
333
334 errln(msg1 + prettySource + msg2 + prettyTarget);
335 }
336 msg1 = UnicodeString (ok3 ? "Ok: incCompare(" : "FAIL: incCompare(");
337 msg2 = ", ";
338 msg3 = ") returned ";
339
340 appendCompareResult(incResult, sResult);
341
342 if (ok3) {
343 logln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult);
344 } else {
345 errln(msg1 + prettySource + msg2 + prettyTarget + msg3 + sResult + msg4 + sExpect);
346 }
347 }
348}
349
350UnicodeString&
351IntlTestCollator::appendCompareResult(Collator::EComparisonResult result,
352 UnicodeString& target)
353{
354 if (result == Collator::LESS)
355 {
356 target += "LESS";
357 }
358 else if (result == Collator::EQUAL)
359 {
360 target += "EQUAL";
361 }
362 else if (result == Collator::GREATER)
363 {
364 target += "GREATER";
365 }
366 else
367 {
368 UnicodeString huh = "?";
369
370 target += (huh + (int32_t)result);
371 }
372
373 return target;
374}
375
376// Produce a printable representation of a CollationKey
377UnicodeString &IntlTestCollator::prettify(const CollationKey &source, UnicodeString &target)
378{
379 int32_t i, byteCount;
380 const uint8_t *bytes = source.getByteArray(byteCount);
381
382 target.remove();
383 target += "[";
384
385 for (i = 0; i < byteCount; i += 1)
386 {
387 appendHex(bytes[i], 2, target);
388 target += " ";
389 }
390
391 target += "]";
392
393 return target;
394}
395
396void IntlTestCollator::backAndForth(CollationElementIterator &iter)
397{
398 // Run through the iterator forwards and stick it into an array
399 int32_t orderLength = 0;
46f4442e 400 Order *orders = getOrders(iter, orderLength);
b75a7d8f
A
401 UErrorCode status = U_ZERO_ERROR;
402
403 // Now go through it backwards and make sure we get the same values
404 int32_t index = orderLength;
405 int32_t o;
406
407 // reset the iterator
408 iter.reset();
409
410 while ((o = iter.previous(status)) != CollationElementIterator::NULLORDER)
411 {
46f4442e
A
412 int32_t offset = iter.getOffset();
413
374ca955
A
414 if (index == 0) {
415 if(o == 0) {
416 continue;
417 } else { // this is an error, orders exhausted but there are non-ignorable CEs from
418 // going backwards
419 errln("Backward iteration returned a non ignorable after orders are exhausted");
420 break;
46f4442e 421 }
374ca955 422 }
46f4442e
A
423
424 index -= 1;
425 if (o != orders[index].order) {
b75a7d8f 426 if (o == 0)
46f4442e
A
427 index += 1;
428 else {
429 while (index > 0 && orders[--index].order == 0) {
430 // nothing...
b75a7d8f 431 }
46f4442e
A
432
433 if (o != orders[index].order) {
434 errln("Mismatched order at index %d: 0x%0:8X vs. 0x%0:8X", index,
435 orders[index].order, o);
436 //break;
437 goto bail;
b75a7d8f
A
438 }
439 }
440 }
46f4442e
A
441
442#if TEST_OFFSETS
443 if (offset != orders[index].offset) {
444 errln("Mismatched offset at index %d: %d vs. %d", index,
445 orders[index].offset, offset);
446 //break;
447 goto bail;
448 }
449#endif
450
b75a7d8f
A
451 }
452
46f4442e 453 while (index != 0 && orders[index - 1].order == 0)
b75a7d8f
A
454 {
455 index --;
456 }
457
458 if (index != 0)
459 {
460 UnicodeString msg("Didn't get back to beginning - index is ");
461 errln(msg + index);
462
463 iter.reset();
464 err("next: ");
465 while ((o = iter.next(status)) != CollationElementIterator::NULLORDER)
466 {
467 UnicodeString hexString("0x");
468
469 appendHex(o, 8, hexString);
470 hexString += " ";
471 err(hexString);
472 }
473 errln("");
474
475 err("prev: ");
476 while ((o = iter.previous(status)) != CollationElementIterator::NULLORDER)
477 {
478 UnicodeString hexString("0x");
479
480 appendHex(o, 8, hexString);
481 hexString += " ";
482 err(hexString);
483 }
484 errln("");
485 }
486
46f4442e 487bail:
b75a7d8f
A
488 delete[] orders;
489}
490
491
492/**
493 * Return an integer array containing all of the collation orders
494 * returned by calls to next on the specified iterator
495 */
46f4442e 496IntlTestCollator::Order *IntlTestCollator::getOrders(CollationElementIterator &iter, int32_t &orderLength)
b75a7d8f
A
497{
498 int32_t maxSize = 100;
499 int32_t size = 0;
46f4442e 500 Order *orders = new Order[maxSize];
b75a7d8f 501 UErrorCode status = U_ZERO_ERROR;
46f4442e 502 int32_t offset = iter.getOffset();
b75a7d8f
A
503
504 int32_t order;
505 while ((order = iter.next(status)) != CollationElementIterator::NULLORDER)
506 {
507 if (size == maxSize)
508 {
509 maxSize *= 2;
46f4442e 510 Order *temp = new Order[maxSize];
b75a7d8f 511
46f4442e 512 uprv_memcpy(temp, orders, size * sizeof(Order));
b75a7d8f
A
513 delete[] orders;
514 orders = temp;
515 }
516
46f4442e
A
517 orders[size].order = order;
518 orders[size].offset = offset;
519
520 offset = iter.getOffset();
521 size += 1;
b75a7d8f
A
522 }
523
524 if (maxSize > size)
525 {
46f4442e 526 Order *temp = new Order[size];
b75a7d8f 527
46f4442e 528 uprv_memcpy(temp, orders, size * sizeof(Order));
b75a7d8f
A
529 delete[] orders;
530 orders = temp;
531 }
532
533 orderLength = size;
534 return orders;
535}
536
537#endif /* #if !UCONFIG_NO_COLLATION */