4297637214
X-SVN-Rev: 8564
381 lines
11 KiB
C
381 lines
11 KiB
C
/********************************************************************
|
|
* 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<currentSequenceLen && !done) {
|
|
/*currChar= seq.next32PostInc();*/
|
|
UTF_NEXT_CHAR(currentSequence, i, currentSequenceLen, currChar);
|
|
if(!quoted) {
|
|
if(u_isWhitespace(currChar)) {
|
|
continue;
|
|
}
|
|
switch(currChar) {
|
|
case 0x003C /* < */:
|
|
*relation = UCOL_LESS;
|
|
done = TRUE;
|
|
break;
|
|
case 0x003D /* = */:
|
|
*relation = UCOL_EQUAL;
|
|
done = TRUE;
|
|
break;
|
|
case 0x003E /* > */:
|
|
*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);
|
|
}
|
|
}
|
|
|
|
|
|
|