/******************************************************************** * COPYRIGHT: * Copyright (c) 1997-2001, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ /** * IntlTestCollator is the medium level test class for everything in the directory "collate". */ /*********************************************************************** * Modification history * Date Name Description * 02/14/2001 synwee Compare with cintltst and commented away tests * that are not run. ***********************************************************************/ #include "dadrcoll.h" #include "unicode/utypes.h" #include "unicode/uchar.h" #include "cstring.h" #include "ucol_tok.h" #include "callcoll.h" static UResourceBundle *parsing = NULL; static UResourceBundle *purpose = NULL; static UResourceBundle *currentTest = NULL; static UResourceBundle *testData = NULL; static UResourceBundle *testBundle = NULL; static int32_t numberOfTests = 0; static UBool dataTestValid = TRUE; /* sequence that is read for testing */ static const UChar *currentSequence = NULL; static int32_t currentSequenceLen = 0; /* TODO: this is bad - be smarter, although if on level with IntlTest, it might be good */ static char* _testDataPath=NULL; /* Get test data from ResourceBundles */ static UResourceBundle* getTestBundle(const char* bundleName) { UErrorCode status = U_ZERO_ERROR; UResourceBundle *testBundle = NULL; const char* icu_data = (char*)loadTestData(&status); char testBundlePath[256] = {'\0'}; strcpy(testBundlePath, icu_data); /*strcat(testBundlePath, U_FILE_SEP_STRING".."U_FILE_SEP_STRING"build"U_FILE_SEP_STRING);*/ if (testBundle == NULL) { testBundle = ures_openDirect(testBundlePath, bundleName, &status); if (status != U_ZERO_ERROR) { log_err("Failed: could not load test data from resourcebundle: %s", bundleName); dataTestValid = FALSE; } } return testBundle; } static void openDataDrivenCollatorTest(void) { UErrorCode status = U_ZERO_ERROR; parsing = NULL; purpose = NULL; currentTest = NULL; testData = NULL; testBundle = NULL; numberOfTests = 0; dataTestValid = TRUE; testBundle = getTestBundle("DataDrivenCollationTest"); if(dataTestValid) { purpose = ures_getByKey(testBundle, "TestPurpose", NULL, &status); parsing = ures_getByKey(testBundle, "TestDataParsing", NULL, &status); testData = ures_getByKey(testBundle, "TestData", NULL, &status); numberOfTests = ures_getSize(testData); if(status != U_ZERO_ERROR) { log_err("Unable to initalize test data - missing mandatory description resources!"); dataTestValid = FALSE; } currentTest = NULL; } } void closeDataDrivenCollatorTest(void) { ures_close(parsing); parsing = NULL; ures_close(purpose); purpose = NULL; ures_close(currentTest); currentTest = NULL; ures_close(testData); testData = NULL; ures_close(testBundle); testBundle = NULL; } /* Reads the options string and sets appropriate attributes in collator */ static void processArguments(UCollator *col, const UChar *start, int32_t optLen, UErrorCode *status) { const UChar *end = start+optLen; UColAttribute attrib; UColAttributeValue value; start = ucol_tok_getNextArgument(start, end, &attrib, &value, status); while(start != NULL) { if(U_SUCCESS(*status)) { ucol_setAttribute(col, attrib, value, status); } start = ucol_tok_getNextArgument(start, end, &attrib, &value, status); } } /* Parses the sequence to be tested */ static UBool getNextInSequence(UChar *source, UCollationResult *relation, UErrorCode *status) { UBool quoted = FALSE; UBool quotedsingle = FALSE; UBool done = FALSE; UChar32 currChar = 0; int32_t i = 0; int32_t offset = 0; *source = 0; /*source.truncate(0);*/ /*while(currChar != CharacterIterator::DONE) {*/ while(i */: *relation = UCOL_GREATER; done = TRUE; break; case 0x0027 /* ' */: /* very basic quoting */ quoted = TRUE; quotedsingle = FALSE; break; case 0x005c /* \ */: /* single quote */ quoted = TRUE; quotedsingle = TRUE; break; default: UTF_APPEND_CHAR(source, offset, 256, currChar); /*source.append(currChar);*/ } } else { if(currChar == 0x0027) { quoted = FALSE; } else { UTF_APPEND_CHAR(source, offset, 256, currChar); /*source.append(currChar);*/ } if(quotedsingle) { quoted = FALSE; } } } if(quoted == TRUE) { *status = U_ILLEGAL_ARGUMENT_ERROR; log_err("Quote in sequence not closed!"); return FALSE; } source[offset] = 0; currentSequence += i; currentSequenceLen -= i; return (currentSequenceLen > 0); } static UBool setTestSequence(const UChar *setSequence, int32_t len, UChar *source, UCollationResult *relation, UErrorCode *status) { /*seq.setText(setSequence);*/ currentSequence = setSequence; currentSequenceLen = len; return getNextInSequence(source, relation, status); } static void processSequence(UCollator* col, const UChar *sequence, int32_t len, UErrorCode *status) { UChar sourceBuff[256]; UChar targetBuff[256]; UChar *source = sourceBuff; UChar *target = targetBuff; UCollationResult relation; UCollationResult nextRelation; UBool hasNext; setTestSequence(sequence, len, source, &relation, status); /* TODO: have a smarter tester that remembers the sequence and ensures that */ /* the complete sequence is in order. That is why I have made a constraint */ /* in the sequence format. */ do { hasNext = getNextInSequence(target, &nextRelation, status); doTest(col, source, target, relation); /*source = target;*/ if(source == sourceBuff) { source = targetBuff; target = sourceBuff; } else { source = sourceBuff; target = targetBuff; } relation = nextRelation; } while(hasNext); } /* Goes through the list of sequences */ /* and runs test for each sequence */ static void processReadyCollator(UResourceBundle *test, UCollator *col, UErrorCode *status) { UResourceBundle *testData = ures_getByKey(test, "TestData", NULL, status); const char *key = NULL; const UChar *sequence = NULL; int32_t len = 0; if(*status == U_ZERO_ERROR) { while(ures_hasNext(testData)) { sequence = ures_getNextString(testData, &len, &key, status); if(VERBOSITY) { log_verbose("Testing sequence: %s\n", aescstrdup(sequence, len)); } processSequence(col, sequence, len, status); } ures_close(testData); } else { log_err("Unable to get test data!"); } } /* Goes through the list of options and executes test data for each individual option. */ /* If there are no options, just does the test data. */ static void processCollatorTests(UResourceBundle *test, UCollator *col, UErrorCode *status) { const UChar *options = NULL; const char *key = NULL; int32_t len = 0; UResourceBundle *optionsRes = NULL; *status = U_ZERO_ERROR; optionsRes = ures_getByKey(test, "Arguments", NULL, status); if(*status == U_ZERO_ERROR) { while(ures_hasNext(optionsRes)) { options = ures_getNextString(optionsRes, &len, &key, status); processArguments(col, options, len, status); if(U_SUCCESS(*status)) { if(VERBOSITY) { log_verbose("Arguments: %s\n", aescstrdup(options, len)); } processReadyCollator(test, col, status); } else { log_err("Error processing arguments!"); } } ures_close(optionsRes); } else { processReadyCollator(test, col, status); } } static void processTest(UResourceBundle *test, UErrorCode *status) { UCollator *col = NULL; const UChar *colString = NULL; const char* key = NULL; int32_t len = 0; UParseError parseError; UResourceBundle *type = NULL; type = ures_getByKey(test, "TestLocale", NULL, status); if(*status == U_ZERO_ERROR) { /* this is a case where we have locale */ while(ures_hasNext(type)) { const UChar* locale = ures_getNextString(type, &len, &key, status); char localeName[256]; u_UCharsToChars(locale, localeName, len); localeName[len] = 0; col = ucol_open(localeName, status); if(U_SUCCESS(*status)) { log_verbose("Testing collator for locale %s\n", localeName); processCollatorTests(test, col, status); ucol_close(col); } else { log_err("Unable to instantiate collator for locale %s\n", localeName); } } } *status = U_ZERO_ERROR; type = ures_getByKey(test, "TestRules", type, status); if(*status == U_ZERO_ERROR) { /* here we deal with rules */ while(ures_hasNext(type)) { colString = ures_getNextString(type, &len, &key, status); col = ucol_openRules(colString, len, UCOL_DEFAULT, UCOL_DEFAULT, &parseError, status); if(U_SUCCESS(*status)) { if(VERBOSITY) { log_verbose("Testing collator for rules %s\n", aescstrdup(colString, len)); /*+UnicodeString(colString));*/ } processCollatorTests(test, col, status); ucol_close(col); } else { if(VERBOSITY) { log_err("Unable to instantiate collator for rules %s\n", aescstrdup(colString, len)); /*+UnicodeString(colString));*/ } } } } *status = U_ZERO_ERROR; ures_close(type); } /* executed a named test from resource bundle */ /* argument check is done on upper level */ static void DataDrivenTest(void) { UErrorCode status = U_ZERO_ERROR; const char* testName = NULL; const char* requestedTest = getTestName(); currentTest = ures_getByKey(testData, requestedTest, currentTest, &status); processTest(currentTest, &status); } /* not used, enumerates and executes all the tests in resource bundle */ static void DoAllDataDrivenTests(void) { UErrorCode status = U_ZERO_ERROR; const char* testName = NULL; const char* requestedTest = getTestName(); openDataDrivenCollatorTest(); ures_resetIterator(testData); while(ures_hasNext(testData)) { currentTest = ures_getNextResource(testData, currentTest, &status); testName = ures_getKey(currentTest); log_verbose("%s\n", testName); processTest(currentTest, &status); } closeDataDrivenCollatorTest(); } /* enumerates over tests and adds them to the test list */ void addDataDrivenTest(TestNode** root) { UErrorCode status = U_ZERO_ERROR; const char* testName = NULL; char testToAdd[256]; openDataDrivenCollatorTest(); ures_resetIterator(testData); while(ures_hasNext(testData)) { currentTest = ures_getNextResource(testData, currentTest, &status); testName = ures_getKey(currentTest); strcpy(testToAdd, "tscoll/DataDrivenTest/"); strcat(testToAdd, testName); addTest(root, &DataDrivenTest, testToAdd); } }