/******************************************************************** * COPYRIGHT: * Copyright (c) 1997-1999, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /******************************************************************************** * * File CITERTST.C * * Modification History: * Date Name Description * Madhu Katragadda Ported for C API * 02/19/01 synwee Modified test case for new collation iterator *********************************************************************************/ /* * Collation Iterator tests. * (Let me reiterate my position...) */ #include #include #include "unicode/utypes.h" #include "unicode/ucol.h" #include "unicode/uloc.h" #include "unicode/uchar.h" #include "cintltst.h" #include "citertst.h" #include "unicode/ustring.h" #include "cmemory.h" #define ARRAY_LENGTH(array) (sizeof array / sizeof array[0]) void addCollIterTest(TestNode** root) { addTest(root, &TestPrevious, "tscoll/citertst/TestPrevious"); addTest(root, &TestOffset, "tscoll/citertst/TestOffset"); addTest(root, &TestSetText, "tscoll/citertst/TestSetText"); addTest(root, &TestMaxExpansion, "tscoll/citertst/TestMaxExpansion"); addTest(root, &TestUnicodeChar, "tscoll/citertst/TestUnicodeChar"); } /** * Test for CollationElementIterator previous and next for the whole set of * unicode characters. */ static void TestUnicodeChar() { UChar source[0xFF]; UCollator *en_us; UCollationElements *iter; UErrorCode status = U_ZERO_ERROR; UChar codepoint; UChar *test; en_us = ucol_open("en_US", &status); for (codepoint = 1; codepoint < 0xFFFE;) { test = source; while (codepoint % 0xFF != 0) { if (u_isdefined(codepoint)) *(test ++) = codepoint; codepoint ++; } if (u_isdefined(codepoint)) *(test ++) = codepoint; if (codepoint != 0xFFFF) codepoint ++; *test = 0; iter=ucol_openElements(en_us, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(en_us); return; } /* A basic test to see if it's working at all */ backAndForth(iter); ucol_closeElements(iter); } ucol_close(en_us); } /** * Test for CollationElementIterator.previous() * * @bug 4108758 - Make sure it works with contracting characters * */ static void TestPrevious() { UCollator *coll=NULL; UChar rule[50]; UChar *source; UCollator *c1, *c2, *c3; UCollationElements *iter; UErrorCode status = U_ZERO_ERROR; test1=(UChar*)malloc(sizeof(UChar) * 50); test2=(UChar*)malloc(sizeof(UChar) * 50); u_uastrcpy(test1, "What subset of all possible test cases?"); u_uastrcpy(test2, "has the highest probability of detecting"); coll = ucol_open("coll", &status); iter=ucol_openElements(coll, test1, u_strlen(test1), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(coll); return; } /* A basic test to see if it's working at all */ backAndForth(iter); ucol_closeElements(iter); ucol_close(coll); /* Test with a contracting character sequence */ u_uastrcpy(rule, "&a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH"); c1 = ucol_openRules(rule, u_strlen(rule), UCOL_NO_NORMALIZATION, UCOL_DEFAULT_STRENGTH, &status); /* synwee : temporarily changed c1 = ucol_open("es_ES", &status); */ if (c1 == NULL || U_FAILURE(status)) { log_err("Couldn't create a RuleBasedCollator with a contracting sequence\n %s\n", myErrorName(status)); return; } source=(UChar*)malloc(sizeof(UChar) * 20); u_uastrcpy(source, "abchdcba"); iter=ucol_openElements(c1, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); return; } backAndForth(iter); ucol_closeElements(iter); ucol_close(c1); free(source); /* Test with an expanding character sequence */ u_uastrcpy(rule, "&a < b < c/abd < d"); c2 = ucol_openRules(rule, u_strlen(rule), UCOL_NO_NORMALIZATION, UCOL_DEFAULT_STRENGTH, &status); if (c2 == NULL || U_FAILURE(status)) { log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n", myErrorName(status)); return; } source=(UChar*)malloc(sizeof(UChar) * 5); u_uastrcpy(source, "abcd"); iter=ucol_openElements(c2, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); return; } backAndForth(iter); ucol_closeElements(iter); ucol_close(c2); free(source); /* Now try both */ u_uastrcpy(rule, "&a < b < c/aba < d < z < ch"); c3 = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT_NORMALIZATION, UCOL_DEFAULT_STRENGTH, &status); if (c3 == NULL || U_FAILURE(status)) { log_err("Couldn't create a RuleBasedCollator with a contracting sequence.\n %s\n", myErrorName(status)); return; } source=(UChar*)malloc(sizeof(UChar) * 10); u_uastrcpy(source, "abcdbchdc"); iter=ucol_openElements(c3, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); return; } backAndForth(iter); ucol_closeElements(iter); ucol_close(c3); source[0] = 0x0e41; source[1] = 0x0e02; source[2] = 0x0e41; source[3] = 0x0e02; source[4] = 0x0e27; source[5] = 0x61; source[6] = 0x62; source[7] = 0x63; source[8] = 0; coll = ucol_open("th_TH", &status); iter=ucol_openElements(coll, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); return; } backAndForth(iter); ucol_closeElements(iter); ucol_close(coll); /* prev test */ source[0] = 0x0061; source[1] = 0x30CF; source[2] = 0x3099; source[3] = 0x30FC; source[4] = 0; coll = ucol_open("ja_JP", &status); iter=ucol_openElements(coll, source, u_strlen(source), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); return; } backAndForth(iter); ucol_closeElements(iter); ucol_close(coll); free(source); free(test1); free(test2); } /** * Test for getOffset() and setOffset() */ static void TestOffset() { UErrorCode status= U_ZERO_ERROR; UCollator *en_us=NULL; UCollationElements *iter, *pristine; int32_t offset; int32_t *orders; int32_t orderLength=0; test1=(UChar*)malloc(sizeof(UChar) * 50); test2=(UChar*)malloc(sizeof(UChar) * 50); u_uastrcpy(test1, "What subset of all possible test cases?"); u_uastrcpy(test2, "has the highest probability of detecting"); en_us = ucol_open("en_US", &status); log_verbose("Testing getOffset and setOffset for CollationElements\n"); iter=ucol_openElements(en_us, test1, u_strlen(test1), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(en_us); return; } /* Run all the way through the iterator, then get the offset */ orders = getOrders(iter, &orderLength); offset = ucol_getOffset(iter); if (offset != u_strlen(test1)) { log_err("offset at end != length %d vs %d\n", offset, u_strlen(test1) ); } /* Now set the offset back to the beginning and see if it works */ pristine=ucol_openElements(en_us, test1, u_strlen(test1), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(en_us); return; } status = U_ZERO_ERROR; ucol_setOffset(iter, 0, &status); if (U_FAILURE(status)) { log_err("setOffset failed. %s\n", myErrorName(status)); } else { assertEqual(iter, pristine); } ucol_closeElements(pristine); ucol_closeElements(iter); free(orders); ucol_close(en_us); free(test1); free(test2); } /** * Test for setText() */ static void TestSetText() { int32_t c,i; UErrorCode status = U_ZERO_ERROR; UCollator *en_us=NULL; UCollationElements *iter1, *iter2; test1=(UChar*)malloc(sizeof(UChar) * 50); test2=(UChar*)malloc(sizeof(UChar) * 50); u_uastrcpy(test1, "What subset of all possible test cases?"); u_uastrcpy(test2, "has the highest probability of detecting"); en_us = ucol_open("en_US", &status); log_verbose("testing setText for Collation elements\n"); iter1=ucol_openElements(en_us, test1, u_strlen(test1), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator1 using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(en_us); return; } iter2=ucol_openElements(en_us, test2, u_strlen(test2), &status); if(U_FAILURE(status)){ log_err("ERROR: in creation of collation element iterator2 using ucol_openElements()\n %s\n", myErrorName(status)); ucol_close(en_us); return; } /* Run through the second iterator just to exercise it */ c = ucol_next(iter2, &status); i = 0; while ( ++i < 10 && (c != UCOL_NULLORDER)) { if (U_FAILURE(status)) { log_err("iter2->next() returned an error. %s\n", myErrorName(status)); ucol_closeElements(iter2); ucol_closeElements(iter1); ucol_close(en_us); return; } c = ucol_next(iter2, &status); } /* Now set it to point to the same string as the first iterator */ ucol_setText(iter2, test1, u_strlen(test1), &status); if (U_FAILURE(status)) { log_err("call to iter2->setText(test1) failed. %s\n", myErrorName(status)); } else { assertEqual(iter1, iter2); } ucol_closeElements(iter2); ucol_closeElements(iter1); ucol_close(en_us); free(test1); free(test2); } static void backAndForth(UCollationElements *iter) { /* Run through the iterator forwards and stick it into an array */ int32_t index, o; UErrorCode status = U_ZERO_ERROR; int32_t orderLength = 0; int32_t *orders; orders= getOrders(iter, &orderLength); /* Now go through it backwards and make sure we get the same values */ index = orderLength; ucol_reset(iter); /* synwee : changed */ while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) { if (o != orders[-- index]) { if (o == 0) index ++; else { while (index > 0 && orders[-- index] == 0) { } if (o != orders[index]) { log_err("Mismatch at index : %d\n", index); break; } } } } while (index != 0 && orders[index - 1] == 0) { index --; } if (index != 0) { log_err("Didn't get back to beginning - index is %d\n", index); ucol_reset(iter); log_err("\nnext: "); while ((o = ucol_next(iter, &status)) != UCOL_NULLORDER) { log_err("Error at %d\n", o); } log_err("\nprev: "); while ((o = ucol_previous(iter, &status)) != UCOL_NULLORDER) { log_err("Error at %d\n", o); } log_verbose("\n"); } free(orders); } /** @bug 4108762 * Test for getMaxExpansion() */ static void TestMaxExpansion() { UErrorCode status = U_ZERO_ERROR; UCollator *coll ;/*= ucol_open("en_US", &status);*/ UChar ch = 0; UCollationElements *iter ;/*= ucol_openElements(coll, &ch, 1, &status);*/ int count = 1; UChar rule[256]; u_uastrcpy(rule, "&a < ab < c/aba < d < z < ch"); coll = ucol_openRules(rule, u_strlen(rule), UCOL_DEFAULT_NORMALIZATION, UCOL_DEFAULT_STRENGTH, &status); iter = ucol_openElements(coll, &ch, 1, &status); while (ch < 0xFFFF && U_SUCCESS(status)) { int count = 1; uint32_t order = 0; ch ++; ucol_setText(iter, &ch, 1, &status); order = ucol_previous(iter, &status); /* thai management */ if (order == 0) order = ucol_previous(iter, &status); while (U_SUCCESS(status) && ucol_previous(iter, &status) != UCOL_NULLORDER) { count ++; } if (U_FAILURE(status) && ucol_getMaxExpansion(iter, order) < count) { log_err("Failure at codepoint %d, maximum expansion count < %d\n", ch, count); } } ucol_closeElements(iter); ucol_close(coll); } /** * Return an integer array containing all of the collation orders * returned by calls to next on the specified iterator */ static int32_t* getOrders(UCollationElements *iter, int32_t *orderLength) { UErrorCode status; int32_t order; int32_t maxSize = 100; int32_t size = 0; int32_t *temp; int32_t *orders =(int32_t*)malloc(sizeof(int32_t) * maxSize); status= U_ZERO_ERROR; while ((order=ucol_next(iter, &status)) != UCOL_NULLORDER) { if (size == maxSize) { maxSize *= 2; temp = (int32_t*)malloc(sizeof(int32_t) * maxSize); memcpy(temp, orders, size * sizeof(int32_t)); free(orders); orders = temp; } orders[size++] = order; } if (maxSize > size) { temp = (int32_t*)malloc(sizeof(int32_t) * size); memcpy(temp, orders, size * sizeof(int32_t)); free(orders); orders = temp; } *orderLength = size; return orders; } static void assertEqual(UCollationElements *i1, UCollationElements *i2) { int32_t c1, c2; int32_t count = 0; UErrorCode status = U_ZERO_ERROR; do { c1 = ucol_next(i1, &status); c2 = ucol_next(i2, &status); if (c1 != c2) { log_err("Error in iteration %d assetEqual between\n %d and %d, they are not equal\n", count, c1, c2); break; } count += 1; } while (c1 != UCOL_NULLORDER); }