• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /********************************************************************
2  * COPYRIGHT:
3  * Copyright (c) 1997-2007, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  ********************************************************************/
6 /*******************************************************************************
7 *
8 * File CALLCOLL.C
9 *
10 * Modification History:
11 *        Name                     Description
12 *     Madhu Katragadda              Ported for C API
13 ********************************************************************************
14 */
15 
16 /*
17  * Important: This file is included into intltest/allcoll.cpp so that the
18  * test data is shared. This makes it easier to maintain the test data,
19  * especially since the Unicode data must be portable and quoted character
20  * literals will not work.
21  * If it is included, then there will be a #define INCLUDE_CALLCOLL_C
22  * that must prevent the actual code in here from being part of the
23  * allcoll.cpp compilation.
24  */
25 
26 /**
27  * CollationDummyTest is a third level test class.  This tests creation of
28  * a customized collator object.  For example, number 1 to be sorted
29  * equlivalent to word 'one'.
30  */
31 
32 #include <string.h>
33 #include <stdlib.h>
34 
35 #include "unicode/utypes.h"
36 
37 #if !UCONFIG_NO_COLLATION
38 
39 #include "unicode/ucol.h"
40 #include "unicode/uloc.h"
41 #include "unicode/ucoleitr.h"
42 #include "unicode/ustring.h"
43 #include "unicode/uclean.h"
44 #include "unicode/putil.h"
45 #include "unicode/uenum.h"
46 
47 #include "cintltst.h"
48 #include "ccolltst.h"
49 #include "callcoll.h"
50 #include "calldata.h"
51 #include "cstring.h"
52 #include "cmemory.h"
53 #include "ucol_imp.h"
54 
55 /* perform test with strength PRIMARY */
56 static void TestPrimary(void);
57 
58 /* perform test with strength SECONDARY */
59 static void TestSecondary(void);
60 
61 /* perform test with strength tertiary */
62 static void TestTertiary(void);
63 
64 /*perform tests with strength Identical */
65 static void TestIdentical(void);
66 
67 /* perform extra tests */
68 static void TestExtra(void);
69 
70 /* Test jitterbug 581 */
71 static void TestJB581(void);
72 
73 /* Test jitterbug 1401 */
74 static void TestJB1401(void);
75 
76 /* Test [variable top] in the rule syntax */
77 static void TestVariableTop(void);
78 
79 /* Test surrogates */
80 static void TestSurrogates(void);
81 
82 static void TestInvalidRules(void);
83 
84 static void TestJitterbug1098(void);
85 
86 static void TestFCDCrash(void);
87 
88 static void TestJ5298(void);
89 
90 const UCollationResult results[] = {
91     UCOL_LESS,
92     UCOL_LESS, /*UCOL_GREATER,*/
93     UCOL_LESS,
94     UCOL_LESS,
95     UCOL_LESS,
96     UCOL_LESS,
97     UCOL_LESS,
98     UCOL_GREATER,
99     UCOL_GREATER,
100     UCOL_LESS,                                     /*  10 */
101     UCOL_GREATER,
102     UCOL_LESS,
103     UCOL_GREATER,
104     UCOL_GREATER,
105     UCOL_LESS,
106     UCOL_LESS,
107     UCOL_LESS,
108     /*  test primary > 17 */
109     UCOL_EQUAL,
110     UCOL_EQUAL,
111     UCOL_EQUAL,                                    /*  20 */
112     UCOL_LESS,
113     UCOL_LESS,
114     UCOL_EQUAL,
115     UCOL_EQUAL,
116     UCOL_EQUAL,
117     UCOL_LESS,
118     /*  test secondary > 26 */
119     UCOL_EQUAL,
120     UCOL_EQUAL,
121     UCOL_EQUAL,
122     UCOL_EQUAL,
123     UCOL_EQUAL,                                    /*  30 */
124     UCOL_EQUAL,
125     UCOL_LESS,
126     UCOL_EQUAL,                                     /*  34 */
127     UCOL_EQUAL,
128     UCOL_EQUAL,
129     UCOL_LESS                                        /* 37 */
130 };
131 
132 
133 static
uprv_appendByteToHexString(char * dst,uint8_t val)134 void uprv_appendByteToHexString(char *dst, uint8_t val) {
135   uint32_t len = (uint32_t)uprv_strlen(dst);
136   *(dst+len) = T_CString_itosOffset((val >> 4));
137   *(dst+len+1) = T_CString_itosOffset((val & 0xF));
138   *(dst+len+2) = 0;
139 }
140 
141 /* this function makes a string with representation of a sortkey */
sortKeyToString(const UCollator * coll,const uint8_t * sortkey,char * buffer,uint32_t * len)142 static char* U_EXPORT2 sortKeyToString(const UCollator *coll, const uint8_t *sortkey, char *buffer, uint32_t *len) {
143   int32_t strength = UCOL_PRIMARY;
144   uint32_t res_size = 0;
145   UBool doneCase = FALSE;
146 
147   char *current = buffer;
148   const uint8_t *currentSk = sortkey;
149 
150   uprv_strcpy(current, "[");
151 
152   while(strength <= UCOL_QUATERNARY && strength <= coll->strength) {
153     if(strength > UCOL_PRIMARY) {
154       uprv_strcat(current, " . ");
155     }
156     while(*currentSk != 0x01 && *currentSk != 0x00) { /* print a level */
157       uprv_appendByteToHexString(current, *currentSk++);
158       uprv_strcat(current, " ");
159     }
160     if(coll->caseLevel == UCOL_ON && strength == UCOL_SECONDARY && doneCase == FALSE) {
161         doneCase = TRUE;
162     } else if(coll->caseLevel == UCOL_OFF || doneCase == TRUE || strength != UCOL_SECONDARY) {
163       strength ++;
164     }
165     uprv_appendByteToHexString(current, *currentSk++); /* This should print '01' */
166     if(strength == UCOL_QUATERNARY && coll->alternateHandling == UCOL_NON_IGNORABLE) {
167       break;
168     }
169   }
170 
171   if(coll->strength == UCOL_IDENTICAL) {
172     uprv_strcat(current, " . ");
173     while(*currentSk != 0) {
174       uprv_appendByteToHexString(current, *currentSk++);
175       uprv_strcat(current, " ");
176     }
177 
178     uprv_appendByteToHexString(current, *currentSk++);
179   }
180   uprv_strcat(current, "]");
181 
182   if(res_size > *len) {
183     return NULL;
184   }
185 
186   return buffer;
187 }
188 
addAllCollTest(TestNode ** root)189 void addAllCollTest(TestNode** root)
190 {
191 
192 
193     addTest(root, &TestPrimary, "tscoll/callcoll/TestPrimary");
194     addTest(root, &TestSecondary, "tscoll/callcoll/TestSecondary");
195     addTest(root, &TestTertiary, "tscoll/callcoll/TestTertiary");
196     addTest(root, &TestIdentical, "tscoll/callcoll/TestIdentical");
197     addTest(root, &TestExtra, "tscoll/callcoll/TestExtra");
198     addTest(root, &TestJB581, "tscoll/callcoll/TestJB581");
199     addTest(root, &TestVariableTop, "tscoll/callcoll/TestVariableTop");
200     addTest(root, &TestSurrogates, "tscoll/callcoll/TestSurrogates");
201     addTest(root, &TestInvalidRules, "tscoll/callcoll/TestInvalidRules");
202     addTest(root, &TestJB1401, "tscoll/callcoll/TestJB1401");
203     addTest(root, &TestJitterbug1098, "tscoll/callcoll/TestJitterbug1098");
204     addTest(root, &TestFCDCrash, "tscoll/callcoll/TestFCDCrash");
205     addTest(root, &TestJ5298, "tscoll/callcoll/TestJ5298");
206 }
207 
hasCollationElements(const char * locName)208 UBool hasCollationElements(const char *locName) {
209 
210   UErrorCode status = U_ZERO_ERROR;
211   UResourceBundle *ColEl = NULL;
212 
213   UResourceBundle *loc = ures_open(U_ICUDATA_COLL, locName, &status);;
214 
215   if(U_SUCCESS(status)) {
216     status = U_ZERO_ERROR;
217     ColEl = ures_getByKey(loc, "collations", ColEl, &status);
218     if(status == U_ZERO_ERROR) { /* do the test - there are real elements */
219       ures_close(ColEl);
220       ures_close(loc);
221       return TRUE;
222     }
223     ures_close(ColEl);
224     ures_close(loc);
225   }
226   return FALSE;
227 }
228 
compareUsingPartials(UCollator * coll,const UChar source[],int32_t sLen,const UChar target[],int32_t tLen,int32_t pieceSize,UErrorCode * status)229 static UCollationResult compareUsingPartials(UCollator *coll, const UChar source[], int32_t sLen, const UChar target[], int32_t tLen, int32_t pieceSize, UErrorCode *status) {
230   int32_t partialSKResult = 0;
231   UCharIterator sIter, tIter;
232   uint32_t sState[2], tState[2];
233   int32_t sSize = pieceSize, tSize = pieceSize;
234   /*int32_t i = 0;*/
235   uint8_t sBuf[16384], tBuf[16384];
236   if(pieceSize > 16384) {
237     log_err("Partial sortkey size buffer too small. Please consider increasing the buffer!\n");
238     *status = U_BUFFER_OVERFLOW_ERROR;
239     return UCOL_EQUAL;
240   }
241   *status = U_ZERO_ERROR;
242   sState[0] = 0; sState[1] = 0;
243   tState[0] = 0; tState[1] = 0;
244   while(sSize == pieceSize && tSize == pieceSize && partialSKResult == 0) {
245     uiter_setString(&sIter, source, sLen);
246     uiter_setString(&tIter, target, tLen);
247     sSize = ucol_nextSortKeyPart(coll, &sIter, sState, sBuf, pieceSize, status);
248     tSize = ucol_nextSortKeyPart(coll, &tIter, tState, tBuf, pieceSize, status);
249 
250     if(sState[0] != 0 || tState[0] != 0) {
251       /*log_verbose("State != 0 : %08X %08X\n", sState[0], tState[0]);*/
252     }
253     /*log_verbose("%i ", i++);*/
254 
255     partialSKResult = memcmp(sBuf, tBuf, pieceSize);
256   }
257 
258   if(partialSKResult < 0) {
259       return UCOL_LESS;
260   } else if(partialSKResult > 0) {
261     return UCOL_GREATER;
262   } else {
263     return UCOL_EQUAL;
264   }
265 }
266 
doTestVariant(UCollator * myCollation,const UChar source[],const UChar target[],UCollationResult result)267 static void doTestVariant(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
268 {
269     int32_t sortklen1, sortklen2, sortklenmax, sortklenmin;
270     int temp=0, gSortklen1=0,gSortklen2=0;
271     UCollationResult compareResult, compareResulta, keyResult, compareResultIter = result;
272     uint8_t *sortKey1, *sortKey2, *sortKey1a, *sortKey2a;
273     uint32_t sLen = u_strlen(source);
274     uint32_t tLen = u_strlen(target);
275     char buffer[256];
276     uint32_t len;
277     UErrorCode status = U_ZERO_ERROR;
278     UColAttributeValue norm = ucol_getAttribute(myCollation, UCOL_NORMALIZATION_MODE, &status);
279 
280     UCharIterator sIter, tIter;
281     uiter_setString(&sIter, source, sLen);
282     uiter_setString(&tIter, target, tLen);
283     compareResultIter = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
284     if(compareResultIter != result) {
285       log_err("different results in iterative comparison for UTF-16 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
286     }
287 
288     /* convert the strings to UTF-8 and do try comparing with char iterator */
289     if(QUICK <= 0) { /*!QUICK*/
290       char utf8Source[256], utf8Target[256];
291       int32_t utf8SourceLen = 0, utf8TargetLen = 0;
292       u_strToUTF8(utf8Source, 256, &utf8SourceLen, source, sLen, &status);
293       if(U_FAILURE(status)) { /* probably buffer is not big enough */
294         log_verbose("Src UTF-8 buffer too small! Will not compare!\n");
295       } else {
296         u_strToUTF8(utf8Target, 256, &utf8TargetLen, target, tLen, &status);
297         if(U_SUCCESS(status)) { /* probably buffer is not big enough */
298           UCollationResult compareResultUTF8 = result, compareResultUTF8Norm = result;
299           /*UCharIterator sIter, tIter;*/
300           /*log_verbose("Strings converted to UTF-8:%s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));*/
301           uiter_setUTF8(&sIter, utf8Source, utf8SourceLen);
302           uiter_setUTF8(&tIter, utf8Target, utf8TargetLen);
303        /*uiter_setString(&sIter, source, sLen);
304       uiter_setString(&tIter, target, tLen);*/
305           compareResultUTF8 = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
306           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
307           sIter.move(&sIter, 0, UITER_START);
308           tIter.move(&tIter, 0, UITER_START);
309           compareResultUTF8Norm = ucol_strcollIter(myCollation, &sIter, &tIter, &status);
310           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
311           if(compareResultUTF8 != compareResultIter) {
312             log_err("different results in iterative comparison for UTF-16 and UTF-8 encoded strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
313           }
314           if(compareResultUTF8 != compareResultUTF8Norm) {
315             log_err("different results in iterative when normalization is turned on with UTF-8 strings. %s, %s\n", aescstrdup(source,-1), aescstrdup(target,-1));
316           }
317         } else {
318           log_verbose("Target UTF-8 buffer too small! Did not compare!\n");
319         }
320         if(U_FAILURE(status)) {
321           log_verbose("UTF-8 strcoll failed! Ignoring result\n");
322         }
323       }
324     }
325 
326     /* testing the partial sortkeys */
327     if(1) { /*!QUICK*/
328       int32_t i = 0;
329       int32_t partialSizes[] = { 3, 1, 2, 4, 8, 20, 80 }; /* just size 3 in the quick mode */
330       int32_t partialSizesSize = 1;
331       if(QUICK <= 0) {
332         partialSizesSize = 7;
333       }
334       /*log_verbose("partial sortkey test piecesize=");*/
335       for(i = 0; i < partialSizesSize; i++) {
336         UCollationResult partialSKResult = result, partialNormalizedSKResult = result;
337         /*log_verbose("%i ", partialSizes[i]);*/
338 
339         partialSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
340         if(partialSKResult != result) {
341           log_err("Partial sortkey comparison returned wrong result (%i exp. %i): %s, %s (size %i)\n",
342             partialSKResult, result,
343             aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
344         }
345 
346         if(QUICK <= 0 && norm != UCOL_ON) {
347           /*log_verbose("N ");*/
348           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
349           partialNormalizedSKResult = compareUsingPartials(myCollation, source, sLen, target, tLen, partialSizes[i], &status);
350           ucol_setAttribute(myCollation, UCOL_NORMALIZATION_MODE, norm, &status);
351           if(partialSKResult != partialNormalizedSKResult) {
352             log_err("Partial sortkey comparison gets different result when normalization is on: %s, %s (size %i)\n",
353               aescstrdup(source,-1), aescstrdup(target,-1), partialSizes[i]);
354           }
355         }
356       }
357       /*log_verbose("\n");*/
358     }
359 
360 
361     compareResult  = ucol_strcoll(myCollation, source, sLen, target, tLen);
362     compareResulta = ucol_strcoll(myCollation, source, -1,   target, -1);
363     if (compareResult != compareResulta) {
364         log_err("ucol_strcoll result from null terminated and explicit length strings differs.\n");
365     }
366 
367     sortklen1=ucol_getSortKey(myCollation, source, sLen,  NULL, 0);
368     sortklen2=ucol_getSortKey(myCollation, target, tLen,  NULL, 0);
369 
370     sortklenmax = (sortklen1>sortklen2?sortklen1:sortklen2);
371     sortklenmin = (sortklen1<sortklen2?sortklen1:sortklen2);
372 
373     sortKey1 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
374     sortKey1a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
375     ucol_getSortKey(myCollation, source, sLen, sortKey1,  sortklen1+1);
376     ucol_getSortKey(myCollation, source, -1,   sortKey1a, sortklen1+1);
377 
378     sortKey2 =(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
379     sortKey2a=(uint8_t*)malloc(sizeof(uint8_t) * (sortklenmax+1));
380     ucol_getSortKey(myCollation, target, tLen, sortKey2,  sortklen2+1);
381     ucol_getSortKey(myCollation, target, -1,   sortKey2a, sortklen2+1);
382 
383     /* Check that sort key generated with null terminated string is identical  */
384     /*  to that generted with a length specified.                              */
385     if (uprv_strcmp((const char *)sortKey1, (const char *)sortKey1a) != 0 ||
386         uprv_strcmp((const char *)sortKey2, (const char *)sortKey2a) != 0 ) {
387         log_err("Sort Keys from null terminated and explicit length strings differ.\n");
388     }
389 
390     /*memcmp(sortKey1, sortKey2,sortklenmax);*/
391     temp= uprv_strcmp((const char *)sortKey1, (const char *)sortKey2);
392     gSortklen1 = uprv_strlen((const char *)sortKey1)+1;
393     gSortklen2 = uprv_strlen((const char *)sortKey2)+1;
394     if(sortklen1 != gSortklen1){
395         log_err("SortKey length does not match Expected: %i Got: %i\n",sortklen1, gSortklen1);
396         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey1, buffer, &len));
397     }
398     if(sortklen2!= gSortklen2){
399         log_err("SortKey length does not match Expected: %i Got: %i\n", sortklen2, gSortklen2);
400         log_verbose("Generated sortkey: %s\n", sortKeyToString(myCollation, sortKey2, buffer, &len));
401     }
402 
403     if(temp < 0) {
404         keyResult=UCOL_LESS;
405     }
406     else if(temp > 0) {
407         keyResult= UCOL_GREATER;
408     }
409     else {
410         keyResult = UCOL_EQUAL;
411     }
412     reportCResult( source, target, sortKey1, sortKey2, compareResult, keyResult, compareResultIter, result );
413     free(sortKey1);
414     free(sortKey2);
415     free(sortKey1a);
416     free(sortKey2a);
417 
418 }
419 
doTest(UCollator * myCollation,const UChar source[],const UChar target[],UCollationResult result)420 void doTest(UCollator* myCollation, const UChar source[], const UChar target[], UCollationResult result)
421 {
422   if(myCollation) {
423     doTestVariant(myCollation, source, target, result);
424     if(result == UCOL_LESS) {
425       doTestVariant(myCollation, target, source, UCOL_GREATER);
426     } else if(result == UCOL_GREATER) {
427       doTestVariant(myCollation, target, source, UCOL_LESS);
428     } else {
429       doTestVariant(myCollation, target, source, UCOL_EQUAL);
430     }
431   } else {
432     log_data_err("No collator! Any data around?\n");
433   }
434 }
435 
436 
437 /**
438  * Return an integer array containing all of the collation orders
439  * returned by calls to next on the specified iterator
440  */
getOrders(UCollationElements * iter,int32_t * orderLength)441 int32_t* getOrders(UCollationElements *iter, int32_t *orderLength)
442 {
443     UErrorCode status;
444     int32_t order;
445     int32_t maxSize = 100;
446     int32_t size = 0;
447     int32_t *temp;
448     int32_t *orders =(int32_t*)malloc(sizeof(int32_t) * maxSize);
449     status= U_ZERO_ERROR;
450 
451 
452     while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER)
453     {
454         if (size == maxSize)
455         {
456             maxSize *= 2;
457             temp = (int32_t*)malloc(sizeof(int32_t) * maxSize);
458 
459             memcpy(temp, orders, size * sizeof(int32_t));
460             free(orders);
461             orders = temp;
462 
463         }
464 
465         orders[size++] = order;
466     }
467 
468     if (maxSize > size && size > 0)
469     {
470         temp = (int32_t*)malloc(sizeof(int32_t) * size);
471 
472         memcpy(temp, orders, size * sizeof(int32_t));
473         free(orders);
474         orders = temp;
475 
476 
477     }
478 
479     *orderLength = size;
480     return orders;
481 }
482 
483 
484 void
backAndForth(UCollationElements * iter)485 backAndForth(UCollationElements *iter)
486 {
487     /* Run through the iterator forwards and stick it into an array */
488     int32_t index, o;
489     UErrorCode status = U_ZERO_ERROR;
490     int32_t orderLength = 0;
491     int32_t *orders;
492     orders= getOrders(iter, &orderLength);
493 
494 
495     /* Now go through it backwards and make sure we get the same values */
496     index = orderLength;
497     ucol_reset(iter);
498 
499     /* synwee : changed */
500     while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER)
501     {
502         if (o != orders[-- index])
503         {
504         if (o == 0)
505           index ++;
506         else
507         {
508           while (index > 0 && orders[-- index] == 0)
509           {
510           }
511           if (o != orders[index])
512           {
513             log_err("Mismatch at index : 0x%x\n", index);
514             return;
515         }
516 
517         }
518       }
519     }
520 
521     while (index != 0 && orders[index - 1] == 0) {
522       index --;
523     }
524 
525     if (index != 0)
526     {
527         log_err("Didn't get back to beginning - index is %d\n", index);
528 
529         ucol_reset(iter);
530         log_err("\nnext: ");
531         if ((o = ucol_next(iter, &status)) != UCOL_NULLORDER)
532         {
533             log_err("Error at %x\n", o);
534         }
535         log_err("\nprev: ");
536         if ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER)
537         {
538             log_err("Error at %x\n", o);
539         }
540         log_verbose("\n");
541     }
542 
543     free(orders);
544 }
545 
genericOrderingTestWithResult(UCollator * coll,const char * const s[],uint32_t size,UCollationResult result)546 void genericOrderingTestWithResult(UCollator *coll, const char * const s[], uint32_t size, UCollationResult result) {
547   UChar t1[2048] = {0};
548   UChar t2[2048] = {0};
549   UCollationElements *iter;
550   UErrorCode status = U_ZERO_ERROR;
551 
552   uint32_t i = 0, j = 0;
553   log_verbose("testing sequence:\n");
554   for(i = 0; i < size; i++) {
555     log_verbose("%s\n", s[i]);
556   }
557 
558   iter = ucol_openElements(coll, t1, u_strlen(t1), &status);
559   if (U_FAILURE(status)) {
560     log_err("Creation of iterator failed\n");
561   }
562   for(i = 0; i < size-1; i++) {
563     for(j = i+1; j < size; j++) {
564       u_unescape(s[i], t1, 2048);
565       u_unescape(s[j], t2, 2048);
566       doTest(coll, t1, t2, result);
567       /* synwee : added collation element iterator test */
568       ucol_setText(iter, t1, u_strlen(t1), &status);
569       backAndForth(iter);
570       ucol_setText(iter, t2, u_strlen(t2), &status);
571       backAndForth(iter);
572     }
573   }
574   ucol_closeElements(iter);
575 }
576 
genericOrderingTest(UCollator * coll,const char * const s[],uint32_t size)577 void genericOrderingTest(UCollator *coll, const char * const s[], uint32_t size) {
578   genericOrderingTestWithResult(coll, s, size, UCOL_LESS);
579 }
580 
genericLocaleStarter(const char * locale,const char * const s[],uint32_t size)581 void genericLocaleStarter(const char *locale, const char * const s[], uint32_t size) {
582   UErrorCode status = U_ZERO_ERROR;
583   UCollator *coll = ucol_open(locale, &status);
584 
585   log_verbose("Locale starter for %s\n", locale);
586 
587   if(U_SUCCESS(status)) {
588     genericOrderingTest(coll, s, size);
589   } else if(status == U_FILE_ACCESS_ERROR) {
590     log_data_err("Is your data around?\n");
591     return;
592   } else {
593     log_err("Unable to open collator for locale %s\n", locale);
594   }
595   ucol_close(coll);
596 }
597 
genericLocaleStarterWithResult(const char * locale,const char * const s[],uint32_t size,UCollationResult result)598 void genericLocaleStarterWithResult(const char *locale, const char * const s[], uint32_t size, UCollationResult result) {
599   UErrorCode status = U_ZERO_ERROR;
600   UCollator *coll = ucol_open(locale, &status);
601 
602   log_verbose("Locale starter for %s\n", locale);
603 
604   if(U_SUCCESS(status)) {
605     genericOrderingTestWithResult(coll, s, size, result);
606   } else if(status == U_FILE_ACCESS_ERROR) {
607     log_data_err("Is your data around?\n");
608     return;
609   } else {
610     log_err("Unable to open collator for locale %s\n", locale);
611   }
612   ucol_close(coll);
613 }
614 
615 /* currently not used with options */
genericRulesStarterWithOptionsAndResult(const char * rules,const char * const s[],uint32_t size,const UColAttribute * attrs,const UColAttributeValue * values,uint32_t attsize,UCollationResult result)616 void genericRulesStarterWithOptionsAndResult(const char *rules, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
617   UErrorCode status = U_ZERO_ERROR;
618   UChar rlz[RULE_BUFFER_LEN] = { 0 };
619   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
620   uint32_t i;
621 
622   UCollator *coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
623 
624   log_verbose("Rules starter for %s\n", rules);
625 
626   if(U_SUCCESS(status)) {
627     log_verbose("Setting attributes\n");
628     for(i = 0; i < attsize; i++) {
629       ucol_setAttribute(coll, attrs[i], values[i], &status);
630     }
631 
632     genericOrderingTestWithResult(coll, s, size, result);
633   } else {
634     log_err("Unable to open collator with rules %s\n", rules);
635   }
636   ucol_close(coll);
637 }
638 
genericLocaleStarterWithOptionsAndResult(const char * locale,const char * const s[],uint32_t size,const UColAttribute * attrs,const UColAttributeValue * values,uint32_t attsize,UCollationResult result)639 void genericLocaleStarterWithOptionsAndResult(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize, UCollationResult result) {
640   UErrorCode status = U_ZERO_ERROR;
641   uint32_t i;
642 
643   UCollator *coll = ucol_open(locale, &status);
644 
645   log_verbose("Locale starter for %s\n", locale);
646 
647   if(U_SUCCESS(status)) {
648 
649     log_verbose("Setting attributes\n");
650     for(i = 0; i < attsize; i++) {
651       ucol_setAttribute(coll, attrs[i], values[i], &status);
652     }
653 
654     genericOrderingTestWithResult(coll, s, size, result);
655   } else {
656     log_err("Unable to open collator for locale %s\n", locale);
657   }
658   ucol_close(coll);
659 }
660 
genericLocaleStarterWithOptions(const char * locale,const char * const s[],uint32_t size,const UColAttribute * attrs,const UColAttributeValue * values,uint32_t attsize)661 void genericLocaleStarterWithOptions(const char *locale, const char * const s[], uint32_t size, const UColAttribute *attrs, const UColAttributeValue *values, uint32_t attsize) {
662   genericLocaleStarterWithOptionsAndResult(locale, s, size, attrs, values, attsize, UCOL_LESS);
663 }
664 
genericRulesStarterWithResult(const char * rules,const char * const s[],uint32_t size,UCollationResult result)665 void genericRulesStarterWithResult(const char *rules, const char * const s[], uint32_t size, UCollationResult result) {
666   UErrorCode status = U_ZERO_ERROR;
667   UChar rlz[RULE_BUFFER_LEN] = { 0 };
668   uint32_t rlen = u_unescape(rules, rlz, RULE_BUFFER_LEN);
669 
670   UCollator *coll = NULL;
671   coll = ucol_openRules(rlz, rlen, UCOL_DEFAULT, UCOL_DEFAULT,NULL, &status);
672   log_verbose("Rules starter for %s\n", rules);
673 
674   if(U_SUCCESS(status)) {
675     genericOrderingTestWithResult(coll, s, size, result);
676     ucol_close(coll);
677   } else if(status == U_FILE_ACCESS_ERROR) {
678     log_data_err("Is your data around?\n");
679   } else {
680     log_err("Unable to open collator with rules %s\n", rules);
681   }
682 }
683 
genericRulesStarter(const char * rules,const char * const s[],uint32_t size)684 void genericRulesStarter(const char *rules, const char * const s[], uint32_t size) {
685   genericRulesStarterWithResult(rules, s, size, UCOL_LESS);
686 }
687 
TestTertiary()688 static void TestTertiary()
689 {
690     int32_t len,i;
691     UChar *rules;
692     UCollator *myCollation;
693     UErrorCode status=U_ZERO_ERROR;
694     const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
695     len = strlen(str);
696     rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
697     u_uastrcpy(rules, str);
698 
699     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH, NULL, &status);
700     if(U_FAILURE(status)){
701         log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
702     }
703 
704     ucol_setStrength(myCollation, UCOL_TERTIARY);
705     for (i = 0; i < 17 ; i++)
706     {
707         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
708     }
709     free(rules);
710     ucol_close(myCollation);
711     myCollation = 0;
712 }
713 
TestPrimary()714 static void TestPrimary( )
715 {
716     int32_t len,i;
717     UChar *rules;
718     UCollator *myCollation;
719     UErrorCode status=U_ZERO_ERROR;
720     const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
721     len = strlen(str);
722     rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
723     u_uastrcpy(rules, str);
724 
725     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
726     if(U_FAILURE(status)){
727         log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
728     }
729     ucol_setStrength(myCollation, UCOL_PRIMARY);
730 
731     for (i = 17; i < 26 ; i++)
732     {
733 
734         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
735     }
736     free(rules);
737     ucol_close(myCollation);
738     myCollation = 0;
739 }
740 
TestSecondary()741 static void TestSecondary()
742 {
743     int32_t i;
744     int32_t len;
745     UChar *rules;
746     UCollator *myCollation;
747     UErrorCode status=U_ZERO_ERROR;
748     const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
749     len = strlen(str);
750     rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
751     u_uastrcpy(rules, str);
752 
753     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
754     if(U_FAILURE(status)){
755         log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
756     }
757     ucol_setStrength(myCollation, UCOL_SECONDARY);
758     for (i = 26; i < 34 ; i++)
759     {
760         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
761     }
762     free(rules);
763     ucol_close(myCollation);
764     myCollation = 0;
765 }
766 
TestIdentical()767 static void TestIdentical()
768 {
769     int32_t i;
770     int32_t len;
771     UChar *rules = 0;
772     UCollator *myCollation;
773     UErrorCode status=U_ZERO_ERROR;
774     const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
775     len = strlen(str);
776     rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
777     u_uastrcpy(rules, str);
778 
779     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_IDENTICAL, NULL,&status);
780     if(U_FAILURE(status)){
781         log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
782     }
783     for(i= 34; i<37; i++)
784     {
785         doTest(myCollation, testSourceCases[i], testTargetCases[i], results[i]);
786     }
787     free(rules);
788     ucol_close(myCollation);
789     myCollation = 0;
790 }
791 
TestExtra()792 static void TestExtra()
793 {
794     int32_t i, j;
795     int32_t len;
796     UChar *rules;
797     UCollator *myCollation;
798     UErrorCode status = U_ZERO_ERROR;
799     const char* str="& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ";
800     len = strlen(str);
801     rules=(UChar*)malloc(sizeof(UChar*) * (len+1));
802     u_uastrcpy(rules, str);
803 
804     myCollation=ucol_openRules(rules, len, UCOL_OFF, UCOL_DEFAULT_STRENGTH,NULL, &status);
805     if(U_FAILURE(status)){
806         log_err("ERROR: in creation of rule based collator :%s\n", myErrorName(status));
807     }
808     ucol_setStrength(myCollation, UCOL_TERTIARY);
809     for (i = 0; i < COUNT_TEST_CASES-1 ; i++)
810     {
811         for (j = i + 1; j < COUNT_TEST_CASES; j += 1)
812         {
813 
814             doTest(myCollation, testCases[i], testCases[j], UCOL_LESS);
815         }
816     }
817     free(rules);
818     ucol_close(myCollation);
819     myCollation = 0;
820 }
821 
TestJB581(void)822 static void TestJB581(void)
823 {
824     UChar       dispName    [100];
825     int32_t     bufferLen   = 0;
826     UChar       source      [100];
827     UChar       target      [100];
828     UCollationResult result     = UCOL_EQUAL;
829     uint8_t     sourceKeyArray  [100];
830     uint8_t     targetKeyArray  [100];
831     int32_t     sourceKeyOut    = 0,
832                 targetKeyOut    = 0;
833     UCollator   *myCollator = 0;
834     UErrorCode status = U_ZERO_ERROR;
835 
836     /*u_uastrcpy(source, "This is a test.");*/
837     /*u_uastrcpy(target, "THISISATEST.");*/
838     u_uastrcpy(source, "THISISATEST.");
839     u_uastrcpy(target, "Thisisatest.");
840 
841     myCollator = ucol_open("en_US", &status);
842     if (U_FAILURE(status)){
843         bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status);
844         /*Report the error with display name... */
845         log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName);
846         return;
847     }
848     result = ucol_strcoll(myCollator, source, -1, target, -1);
849     /* result is 1, secondary differences only for ignorable space characters*/
850     if (result != 1)
851     {
852         log_err("Comparing two strings with only secondary differences in C failed.\n");
853     }
854     /* To compare them with just primary differences */
855     ucol_setStrength(myCollator, UCOL_PRIMARY);
856     result = ucol_strcoll(myCollator, source, -1, target, -1);
857     /* result is 0 */
858     if (result != 0)
859     {
860         log_err("Comparing two strings with no differences in C failed.\n");
861     }
862     /* Now, do the same comparison with keys */
863     sourceKeyOut = ucol_getSortKey(myCollator, source, -1, sourceKeyArray, 100);
864     targetKeyOut = ucol_getSortKey(myCollator, target, -1, targetKeyArray, 100);
865     bufferLen = ((targetKeyOut > 100) ? 100 : targetKeyOut);
866     if (memcmp(sourceKeyArray, targetKeyArray, bufferLen) != 0)
867     {
868         log_err("Comparing two strings with sort keys in C failed.\n");
869     }
870     ucol_close(myCollator);
871 }
872 
TestJB1401(void)873 static void TestJB1401(void)
874 {
875     UCollator     *myCollator = 0;
876     UErrorCode     status = U_ZERO_ERROR;
877     static UChar   NFD_UnsafeStartChars[] = {
878         0x0f73,          /* Tibetan Vowel Sign II */
879         0x0f75,          /* Tibetan Vowel Sign UU */
880         0x0f81,          /* Tibetan Vowel Sign Reversed II */
881             0
882     };
883     int            i;
884 
885 
886     myCollator = ucol_open("en_US", &status);
887     if (U_FAILURE(status)){
888         int32_t     bufferLen   = 0;
889         UChar       dispName    [100];
890         bufferLen = uloc_getDisplayName("en_US", 0, dispName, 100, &status);
891         /*Report the error with display name... */
892         log_err("ERROR: Failed to create the collator for : \"%s\"\n", dispName);
893         return;
894     }
895     ucol_setAttribute(myCollator, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
896     if (U_FAILURE(status)){
897         log_err("ERROR: Failed to set normalization mode ON for collator.\n");
898         return;
899     }
900 
901     for (i=0; ; i++) {
902         UChar    c;
903         UChar    X[4];
904         UChar    Y[20];
905         UChar    Z[20];
906 
907         /*  Get the next funny character to be tested, and set up the
908          *  three test strings X, Y, Z, consisting of an A-grave + test char,
909          *    in original form, NFD, and then NFC form.
910          */
911         c = NFD_UnsafeStartChars[i];
912         if (c==0) {break;}
913 
914         X[0]=0xC0; X[1]=c; X[2]=0;   /* \u00C0 is A Grave*/
915 
916         unorm_normalize(X, -1, UNORM_NFD, 0, Y, 20, &status);
917         unorm_normalize(Y, -1, UNORM_NFC, 0, Z, 20, &status);
918         if (U_FAILURE(status)){
919             log_err("ERROR: Failed to normalize test of character %x\n", c);
920             return;
921         }
922 
923         /* Collation test.  All three strings should be equal.
924          *   doTest does both strcoll and sort keys, with params in both orders.
925          */
926         doTest(myCollator, X, Y, UCOL_EQUAL);
927         doTest(myCollator, X, Z, UCOL_EQUAL);
928         doTest(myCollator, Y, Z, UCOL_EQUAL);
929 
930         /* Run collation element iterators over the three strings.  Results should be same for each.
931          */
932         {
933             UCollationElements *ceiX, *ceiY, *ceiZ;
934             int32_t             ceX,   ceY,   ceZ;
935             int                 j;
936 
937             ceiX = ucol_openElements(myCollator, X, -1, &status);
938             ceiY = ucol_openElements(myCollator, Y, -1, &status);
939             ceiZ = ucol_openElements(myCollator, Z, -1, &status);
940             if (U_FAILURE(status)) {
941                 log_err("ERROR: uucol_openElements failed.\n");
942                 return;
943             }
944 
945             for (j=0;; j++) {
946                 ceX = ucol_next(ceiX, &status);
947                 ceY = ucol_next(ceiY, &status);
948                 ceZ = ucol_next(ceiZ, &status);
949                 if (U_FAILURE(status)) {
950                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
951                     break;
952                 }
953                 if (ceX != ceY || ceY != ceZ) {
954                     log_err("ERROR: ucol_next failed for iteration #%d.\n", j);
955                     break;
956                 }
957                 if (ceX == UCOL_NULLORDER) {
958                     break;
959                 }
960             }
961             ucol_closeElements(ceiX);
962             ucol_closeElements(ceiY);
963             ucol_closeElements(ceiZ);
964         }
965     }
966     ucol_close(myCollator);
967 }
968 
969 
970 
971 /**
972 * Tests the [variable top] tag in rule syntax. Since the default [alternate]
973 * tag has the value shifted, any codepoints before [variable top] should give
974 * a primary ce of 0.
975 */
TestVariableTop(void)976 static void TestVariableTop(void)
977 {
978     const char       *str          = "&z = [variable top]";
979           int         len          = strlen(str);
980           UChar      *rules;
981           UCollator  *myCollation;
982           UCollator  *enCollation;
983           UErrorCode  status       = U_ZERO_ERROR;
984           UChar       source[1];
985           UChar       ch;
986           uint8_t     result[20];
987           uint8_t     expected[20];
988 
989     rules = (UChar*)malloc(sizeof(UChar*) * (len + 1));
990     u_uastrcpy(rules, str);
991 
992     enCollation = ucol_open("en_US", &status);
993     myCollation = ucol_openRules(rules, len, UCOL_OFF,
994                                  UCOL_PRIMARY,NULL, &status);
995     if (U_FAILURE(status)) {
996         log_err("ERROR: in creation of rule based collator :%s\n",
997                 myErrorName(status));
998         return;
999     }
1000 
1001     ucol_setStrength(enCollation, UCOL_PRIMARY);
1002     ucol_setAttribute(enCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
1003                       &status);
1004     ucol_setAttribute(myCollation, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED,
1005                       &status);
1006 
1007     if (ucol_getAttribute(myCollation, UCOL_ALTERNATE_HANDLING, &status) !=
1008         UCOL_SHIFTED || U_FAILURE(status)) {
1009         log_err("ERROR: ALTERNATE_HANDLING value can not be set to SHIFTED\n");
1010     }
1011 
1012     uprv_memset(expected, 0, 20);
1013 
1014     /* space is supposed to be a variable */
1015     source[0] = ' ';
1016     len = ucol_getSortKey(enCollation, source, 1, result,
1017                           sizeof(result));
1018 
1019     if (uprv_memcmp(expected, result, len) != 0) {
1020         log_err("ERROR: SHIFTED alternate does not return 0 for primary of space\n");
1021     }
1022 
1023     ch = 'a';
1024     while (ch < 'z') {
1025         source[0] = ch;
1026         len = ucol_getSortKey(myCollation, source, 1, result,
1027                               sizeof(result));
1028         if (uprv_memcmp(expected, result, len) != 0) {
1029             log_err("ERROR: SHIFTED alternate does not return 0 for primary of %c\n",
1030                     ch);
1031         }
1032         ch ++;
1033     }
1034 
1035     free(rules);
1036     ucol_close(enCollation);
1037     ucol_close(myCollation);
1038     enCollation = NULL;
1039     myCollation = NULL;
1040 }
1041 
1042 /**
1043   * Tests surrogate support.
1044   * NOTE: This test used \\uD801\\uDC01 pair, which is now assigned to Desseret
1045   * Therefore, another (unassigned) code point was used for this test.
1046   */
TestSurrogates(void)1047 static void TestSurrogates(void)
1048 {
1049     const char       *str          =
1050                               "&z<'\\uD800\\uDC00'<'\\uD800\\uDC0A\\u0308'<A";
1051           int         len          = strlen(str);
1052           int         rlen         = 0;
1053           UChar      *rules;
1054           UCollator  *myCollation;
1055           UCollator  *enCollation;
1056           UErrorCode  status       = U_ZERO_ERROR;
1057           UChar       source[][4]    =
1058           {{'z', 0, 0}, {0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {0xD800, 0xDC02}};
1059           UChar       target[][4]    =
1060           {{0xD800, 0xDC00, 0}, {0xD800, 0xDC0A, 0x0308, 0}, {'A', 0, 0}, {0xD800, 0xDC03}};
1061           int         count        = 0;
1062           uint8_t enresult[20], myresult[20];
1063           int enlen, mylen;
1064 
1065     /* tests for open rules with surrogate rules */
1066     rules = (UChar*)malloc(sizeof(UChar*) * (len + 1));
1067     rlen = u_unescape(str, rules, len);
1068 
1069     enCollation = ucol_open("en_US", &status);
1070     myCollation = ucol_openRules(rules, rlen, UCOL_OFF,
1071                                  UCOL_TERTIARY,NULL, &status);
1072     if (U_FAILURE(status)) {
1073         log_err("ERROR: in creation of rule based collator :%s\n",
1074                 myErrorName(status));
1075         return;
1076     }
1077 
1078     /*
1079     this test is to verify the supplementary sort key order in the english
1080     collator
1081     */
1082     log_verbose("start of english collation supplementary characters test\n");
1083     while (count < 2) {
1084         doTest(enCollation, source[count], target[count], UCOL_LESS);
1085         count ++;
1086     }
1087     doTest(enCollation, source[count], target[count], UCOL_GREATER);
1088 
1089     log_verbose("start of tailored collation supplementary characters test\n");
1090     count = 0;
1091     /* tests getting collation elements for surrogates for tailored rules */
1092     while (count < 4) {
1093         doTest(myCollation, source[count], target[count], UCOL_LESS);
1094         count ++;
1095     }
1096 
1097     /* tests that \uD800\uDC02 still has the same value, not changed */
1098     enlen = ucol_getSortKey(enCollation, source[3], 2, enresult, 20);
1099     mylen = ucol_getSortKey(myCollation, source[3], 2, myresult, 20);
1100     if (enlen != mylen ||
1101         uprv_memcmp(enresult, myresult, enlen) != 0) {
1102         log_verbose("Failed : non-tailored supplementary characters should have the same value\n");
1103     }
1104 
1105     free(rules);
1106     ucol_close(enCollation);
1107     ucol_close(myCollation);
1108     enCollation = NULL;
1109     myCollation = NULL;
1110 }
1111 
1112 /*
1113  *### TODO: Add more invalid rules to test all different scenarios.
1114  *
1115  */
1116 static void
TestInvalidRules()1117 TestInvalidRules(){
1118 #define MAX_ERROR_STATES 2
1119 
1120     static const char* rulesArr[MAX_ERROR_STATES] = {
1121         "& C < ch, cH, Ch[this should fail]<d",
1122         "& C < ch, cH, & Ch[variable top]"
1123     };
1124     static const char* preContextArr[MAX_ERROR_STATES] = {
1125         "his should fail",
1126         "& C < ch, cH, ",
1127 
1128     };
1129     static const char* postContextArr[MAX_ERROR_STATES] = {
1130         "<d",
1131         " Ch[variable t"
1132     };
1133     int i;
1134 
1135     for(i = 0;i<MAX_ERROR_STATES;i++){
1136         UChar rules[1000]       = { '\0' };
1137         UChar preContextExp[1000]  = { '\0' };
1138         UChar postContextExp[1000] = { '\0' };
1139         UParseError parseError;
1140         UErrorCode status = U_ZERO_ERROR;
1141         UCollator* coll=0;
1142         u_charsToUChars(rulesArr[i],rules,uprv_strlen(rulesArr[i])+1);
1143         u_charsToUChars(preContextArr[i],preContextExp,uprv_strlen(preContextArr[i])+1);
1144         u_charsToUChars(postContextArr[i],postContextExp,uprv_strlen(postContextArr[i])+1);
1145         /* clean up stuff in parseError */
1146         u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
1147         u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
1148         /* open the rules and test */
1149         coll = ucol_openRules(rules,u_strlen(rules),UCOL_OFF,UCOL_DEFAULT_STRENGTH,&parseError,&status);
1150         if(u_strcmp(parseError.preContext,preContextExp)!=0){
1151             log_err("preContext in UParseError for ucol_openRules does not match\n");
1152         }
1153         if(u_strcmp(parseError.postContext,postContextExp)!=0){
1154             log_err("postContext in UParseError for ucol_openRules does not match\n");
1155         }
1156     }
1157 }
1158 
1159 static void
TestJitterbug1098()1160 TestJitterbug1098(){
1161     UChar rule[1000];
1162     UCollator* c1 = NULL;
1163     UErrorCode status = U_ZERO_ERROR;
1164     UParseError parseError;
1165     char preContext[200]={0};
1166     char postContext[200]={0};
1167     int i=0;
1168     const char* rules[] = {
1169          "&''<\\\\",
1170          "&\\'<\\\\",
1171          "&\\\"<'\\'",
1172          "&'\"'<\\'",
1173          '\0'
1174 
1175     };
1176     const UCollationResult results1098[] = {
1177         UCOL_LESS,
1178         UCOL_LESS,
1179         UCOL_LESS,
1180         UCOL_LESS,
1181     };
1182     const UChar input[][2]= {
1183         {0x0027,0x005c},
1184         {0x0027,0x005c},
1185         {0x0022,0x005c},
1186         {0x0022,0x0027},
1187     };
1188     UChar X[2] ={0};
1189     UChar Y[2] ={0};
1190     u_memset(parseError.preContext,0x0000,U_PARSE_CONTEXT_LEN);
1191     u_memset(parseError.postContext,0x0000,U_PARSE_CONTEXT_LEN);
1192     for(;rules[i]!=0;i++){
1193         u_uastrcpy(rule, rules[i]);
1194         c1 = ucol_openRules(rule, u_strlen(rule), UCOL_OFF, UCOL_DEFAULT_STRENGTH, &parseError, &status);
1195         if(U_FAILURE(status)){
1196             log_err("Could not parse the rules syntax. Error: %s ", u_errorName(status));
1197 
1198             if (status == U_PARSE_ERROR) {
1199                 u_UCharsToChars(parseError.preContext,preContext,20);
1200                 u_UCharsToChars(parseError.postContext,postContext,20);
1201                 log_verbose("\n\tPre-Context: %s \n\tPost-Context:%s \n",preContext,postContext);
1202             }
1203 
1204             return;
1205         }
1206         X[0] = input[i][0];
1207         Y[0] = input[i][1];
1208         doTest(c1,X,Y,results1098[i]);
1209         ucol_close(c1);
1210     }
1211 }
1212 
1213 /*  These tests do cleanup and reinitialize ICU in the course of their operation.
1214  *    The ICU data directory must be preserved across these operations.
1215  *    Here is a helper function to assist with that.
1216  */
safeGetICUDataDirectory()1217 static char *safeGetICUDataDirectory() {
1218     const char *dataDir = u_getDataDirectory();  /* Returned string vanashes with u_cleanup */
1219     char *retStr = NULL;
1220     if (dataDir != NULL) {
1221         retStr = (char *)malloc(strlen(dataDir)+1);
1222         strcpy(retStr, dataDir);
1223     }
1224     return retStr;
1225 }
1226 
1227 
1228 static void
TestFCDCrash(void)1229 TestFCDCrash(void) {
1230     static const char *test[] = {
1231     "Gr\\u00F6\\u00DFe",
1232     "Grossist"
1233     };
1234 
1235     char *icuDataDir = safeGetICUDataDirectory();
1236     UErrorCode status = U_ZERO_ERROR;
1237     UCollator *coll = ucol_open("es", &status);
1238     if(U_FAILURE(status)) {
1239         log_err("Couldn't open collator\n");
1240         return;
1241     }
1242     ucol_close(coll);
1243     coll = NULL;
1244     u_cleanup();
1245     u_setDataDirectory(icuDataDir);
1246     coll = ucol_open("de_DE", &status);
1247     if(U_FAILURE(status)) {
1248         log_err("Couldn't open collator\n");
1249         return;
1250     }
1251     ucol_setAttribute(coll, UCOL_NORMALIZATION_MODE, UCOL_ON, &status);
1252     genericOrderingTest(coll, test, 2);
1253     ucol_close(coll);
1254     free(icuDataDir);
1255 
1256 }
1257 
1258 /*static UBool
1259 find(UEnumeration* list, const char* str, UErrorCode* status){
1260     const char* value = NULL;
1261     int32_t length=0;
1262     if(U_FAILURE(*status)){
1263         return FALSE;
1264     }
1265     uenum_reset(list, status);
1266     while( (value= uenum_next(list, &length, status))!=NULL){
1267         if(strcmp(value, str)==0){
1268             return TRUE;
1269         }
1270     }
1271     return FALSE;
1272 }*/
1273 
TestJ5298(void)1274 static void TestJ5298(void)
1275 {
1276     UErrorCode status = U_ZERO_ERROR;
1277     char input[256], output[256];
1278     UBool isAvailable;
1279     int32_t i = 0;
1280     UEnumeration* values = NULL;
1281     const char *keywordValue = NULL;
1282     log_verbose("Number of collator locales returned : %i \n", ucol_countAvailable());
1283     values = ucol_getKeywordValues("collation", &status);
1284     for (i = 0; i < ucol_countAvailable(); i++) {
1285         uenum_reset(values, &status);
1286         while ((keywordValue = uenum_next(values, NULL, &status)) != NULL) {
1287             strcpy(input, ucol_getAvailable(i));
1288             if (strcmp(keywordValue, "standard") != 0) {
1289                 strcat(input, "@collation=");
1290                 strcat(input, keywordValue);
1291             }
1292 
1293             ucol_getFunctionalEquivalent(output, 256, "collation", input, &isAvailable, &status);
1294             if (strcmp(input, output) == 0) { /* Unique locale, print it out */
1295                 log_verbose("%s, \n", output);
1296             }
1297         }
1298     }
1299     uenum_close(values);
1300     log_verbose("\n");
1301 }
1302 #endif /* #if !UCONFIG_NO_COLLATION */
1303 
1304