/******************************************************************** * COPYRIGHT: * Copyright (c) 1997-2011, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /******************************************************************************** * * File CBIAPTS.C * * Modification History: * Name Description * Madhu Katragadda Creation *********************************************************************************/ /*C API TEST FOR BREAKITERATOR */ /** * This is an API test. It doesn't test very many cases, and doesn't * try to test the full functionality. It just calls each function in the class and * verifies that it works on a basic level. **/ #include "unicode/utypes.h" #if !UCONFIG_NO_BREAK_ITERATION #include #include #include "unicode/uloc.h" #include "unicode/ubrk.h" #include "unicode/ustring.h" #include "unicode/ucnv.h" #include "unicode/utext.h" #include "cintltst.h" #include "cbiapts.h" #define TEST_ASSERT_SUCCESS(status) {if (U_FAILURE(status)) { \ log_data_err("Failure at file %s, line %d, error = %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));}} #define TEST_ASSERT(expr) {if ((expr)==FALSE) { \ log_data_err("Test Failure at file %s, line %d (Are you missing data?)\n", __FILE__, __LINE__);}} static void TestBreakIteratorSafeClone(void); static void TestBreakIteratorRules(void); static void TestBreakIteratorRuleError(void); static void TestBreakIteratorStatusVec(void); static void TestBreakIteratorUText(void); static void TestBreakIteratorTailoring(void); static void TestBreakIteratorRefresh(void); void addBrkIterAPITest(TestNode** root); void addBrkIterAPITest(TestNode** root) { #if !UCONFIG_NO_FILE_IO addTest(root, &TestBreakIteratorCAPI, "tstxtbd/cbiapts/TestBreakIteratorCAPI"); addTest(root, &TestBreakIteratorSafeClone, "tstxtbd/cbiapts/TestBreakIteratorSafeClone"); addTest(root, &TestBreakIteratorUText, "tstxtbd/cbiapts/TestBreakIteratorUText"); #endif addTest(root, &TestBreakIteratorRules, "tstxtbd/cbiapts/TestBreakIteratorRules"); addTest(root, &TestBreakIteratorRuleError, "tstxtbd/cbiapts/TestBreakIteratorRuleError"); addTest(root, &TestBreakIteratorStatusVec, "tstxtbd/cbiapts/TestBreakIteratorStatusVec"); addTest(root, &TestBreakIteratorTailoring, "tstxtbd/cbiapts/TestBreakIteratorTailoring"); addTest(root, &TestBreakIteratorRefresh, "tstxtbd/cbiapts/TestBreakIteratorRefresh"); } #define CLONETEST_ITERATOR_COUNT 2 /* * Utility function for converting char * to UChar * strings, to * simplify the test code. Converted strings are put in heap allocated * storage. A hook (probably a local in the caller's code) allows all * strings converted with that hook to be freed with a single call. */ typedef struct StringStruct { struct StringStruct *link; UChar str[1]; } StringStruct; static UChar* toUChar(const char *src, void **freeHook) { /* Structure of the memory that we allocate on the heap */ int32_t numUChars; int32_t destSize; UChar stackBuf[2000 + sizeof(void *)/sizeof(UChar)]; StringStruct *dest; UConverter *cnv; UErrorCode status = U_ZERO_ERROR; if (src == NULL) { return NULL; }; cnv = ucnv_open(NULL, &status); if(U_FAILURE(status) || cnv == NULL) { return NULL; } ucnv_reset(cnv); numUChars = ucnv_toUChars(cnv, stackBuf, 2000, src, -1, &status); destSize = (numUChars+1) * sizeof(UChar) + sizeof(struct StringStruct); dest = (StringStruct *)malloc(destSize); if (dest != NULL) { if (status == U_BUFFER_OVERFLOW_ERROR || status == U_STRING_NOT_TERMINATED_WARNING) { ucnv_toUChars(cnv, dest->str, numUChars+1, src, -1, &status); } else if (status == U_ZERO_ERROR) { u_strcpy(dest->str, stackBuf); } else { free(dest); dest = NULL; } } ucnv_reset(cnv); /* be good citizens */ ucnv_close(cnv); if (dest == NULL) { return NULL; } dest->link = (StringStruct*)(*freeHook); *freeHook = dest; return dest->str; } static void freeToUCharStrings(void **hook) { StringStruct *s = *(StringStruct **)hook; while (s != NULL) { StringStruct *next = s->link; free(s); s = next; } } static void TestBreakIteratorCAPI() { UErrorCode status = U_ZERO_ERROR; UBreakIterator *word, *sentence, *line, *character, *b, *bogus; int32_t start,pos,end,to; int32_t i; int32_t count = 0; UChar text[50]; /* Note: the adjacent "" are concatenating strings, not adding a \" to the string, which is probably what whoever wrote this intended. Don't fix, because it would throw off the hard coded break positions in the following tests. */ u_uastrcpy(text, "He's from Africa. ""Mr. Livingston, I presume?"" Yeah"); /*test ubrk_open()*/ log_verbose("\nTesting BreakIterator open functions\n"); /* Use french for fun */ word = ubrk_open(UBRK_WORD, "en_US", text, u_strlen(text), &status); if(status == U_FILE_ACCESS_ERROR) { log_data_err("Check your data - it doesn't seem to be around\n"); return; } else if(U_FAILURE(status)){ log_err_status(status, "FAIL: Error in ubrk_open() for word breakiterator: %s\n", myErrorName(status)); } else{ log_verbose("PASS: Successfully opened word breakiterator\n"); } sentence = ubrk_open(UBRK_SENTENCE, "en_US", text, u_strlen(text), &status); if(U_FAILURE(status)){ log_err_status(status, "FAIL: Error in ubrk_open() for sentence breakiterator: %s\n", myErrorName(status)); return; } else{ log_verbose("PASS: Successfully opened sentence breakiterator\n"); } line = ubrk_open(UBRK_LINE, "en_US", text, u_strlen(text), &status); if(U_FAILURE(status)){ log_err("FAIL: Error in ubrk_open() for line breakiterator: %s\n", myErrorName(status)); return; } else{ log_verbose("PASS: Successfully opened line breakiterator\n"); } character = ubrk_open(UBRK_CHARACTER, "en_US", text, u_strlen(text), &status); if(U_FAILURE(status)){ log_err("FAIL: Error in ubrk_open() for character breakiterator: %s\n", myErrorName(status)); return; } else{ log_verbose("PASS: Successfully opened character breakiterator\n"); } /*trying to open an illegal iterator*/ bogus = ubrk_open((UBreakIteratorType)5, "en_US", text, u_strlen(text), &status); if(U_SUCCESS(status)){ log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n"); } if(U_FAILURE(status)){ if(status != U_ILLEGAL_ARGUMENT_ERROR){ log_err("FAIL: Error in ubrk_open() for BOGUS breakiterator. Expected U_ILLEGAL_ARGUMENT_ERROR\n Got %s\n", myErrorName(status)); } } status=U_ZERO_ERROR; /* ======= Test ubrk_countAvialable() and ubrk_getAvialable() */ log_verbose("\nTesting ubrk_countAvailable() and ubrk_getAvailable()\n"); count=ubrk_countAvailable(); /* use something sensible w/o hardcoding the count */ if(count < 0){ log_err("FAIL: Error in ubrk_countAvialable() returned %d\n", count); } else{ log_verbose("PASS: ubrk_countAvialable() successful returned %d\n", count); } for(i=0;ilocale != NULL; ++testPtr) { UErrorCode status = U_ZERO_ERROR; UBreakIterator* ubrkiter = ubrk_open(testPtr->type, testPtr->locale, testPtr->test, -1, &status); if ( U_SUCCESS(status) ) { int32_t offset, offsindx; UBool foundError; foundError = FALSE; for (offsindx = 0; (offset = ubrk_next(ubrkiter)) != UBRK_DONE; ++offsindx) { if (!foundError && offsindx >= testPtr->numOffsets) { log_err("FAIL: locale %s, break type %d, ubrk_next expected UBRK_DONE, got %d\n", testPtr->locale, testPtr->type, offset); foundError = TRUE; } else if (!foundError && offset != testPtr->offsFwd[offsindx]) { log_err("FAIL: locale %s, break type %d, ubrk_next expected %d, got %d\n", testPtr->locale, testPtr->type, testPtr->offsFwd[offsindx], offset); foundError = TRUE; } } if (!foundError && offsindx < testPtr->numOffsets) { log_err("FAIL: locale %s, break type %d, ubrk_next expected %d, got UBRK_DONE\n", testPtr->locale, testPtr->type, testPtr->offsFwd[offsindx]); } foundError = FALSE; for (offsindx = 0; (offset = ubrk_previous(ubrkiter)) != UBRK_DONE; ++offsindx) { if (!foundError && offsindx >= testPtr->numOffsets) { log_err("FAIL: locale %s, break type %d, ubrk_previous expected UBRK_DONE, got %d\n", testPtr->locale, testPtr->type, offset); foundError = TRUE; } else if (!foundError && offset != testPtr->offsRev[offsindx]) { log_err("FAIL: locale %s, break type %d, ubrk_previous expected %d, got %d\n", testPtr->locale, testPtr->type, testPtr->offsRev[offsindx], offset); foundError = TRUE; } } if (!foundError && offsindx < testPtr->numOffsets) { log_err("FAIL: locale %s, break type %d, ubrk_previous expected %d, got UBRK_DONE\n", testPtr->locale, testPtr->type, testPtr->offsRev[offsindx]); } ubrk_close(ubrkiter); } else { log_err_status(status, "FAIL: locale %s, break type %d, ubrk_open status: %s\n", testPtr->locale, testPtr->type, u_errorName(status)); } } } static void TestBreakIteratorRefresh(void) { /* * RefreshInput changes out the input of a Break Iterator without * changing anything else in the iterator's state. Used with Java JNI, * when Java moves the underlying string storage. This test * runs a ubrk_next() repeatedly, moving the text in the middle of the sequence. * The right set of boundaries should still be found. */ UChar testStr[] = {0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, 0x44, 0x0}; /* = " A B C D" */ UChar movedStr[] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0}; UErrorCode status = U_ZERO_ERROR; UBreakIterator *bi; UText ut1 = UTEXT_INITIALIZER; UText ut2 = UTEXT_INITIALIZER; bi = ubrk_open(UBRK_LINE, "en_US", NULL, 0, &status); TEST_ASSERT_SUCCESS(status); utext_openUChars(&ut1, testStr, -1, &status); TEST_ASSERT_SUCCESS(status); ubrk_setUText(bi, &ut1, &status); TEST_ASSERT_SUCCESS(status); if (U_SUCCESS(status)) { /* Line boundaries will occur before each letter in the original string */ TEST_ASSERT(1 == ubrk_next(bi)); TEST_ASSERT(3 == ubrk_next(bi)); /* Move the string, kill the original string. */ u_strcpy(movedStr, testStr); u_memset(testStr, 0x20, u_strlen(testStr)); utext_openUChars(&ut2, movedStr, -1, &status); TEST_ASSERT_SUCCESS(status); ubrk_refreshUText(bi, &ut2, &status); TEST_ASSERT_SUCCESS(status); /* Find the following matches, now working in the moved string. */ TEST_ASSERT(5 == ubrk_next(bi)); TEST_ASSERT(7 == ubrk_next(bi)); TEST_ASSERT(8 == ubrk_next(bi)); TEST_ASSERT(UBRK_DONE == ubrk_next(bi)); TEST_ASSERT_SUCCESS(status); utext_close(&ut1); utext_close(&ut2); } ubrk_close(bi); } #endif /* #if !UCONFIG_NO_BREAK_ITERATION */