blob: cc64fcf43e3ecc5758228644b484adc4642011db [file] [log] [blame]
/********************************************************************
* 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 "unicode/utypes.h"
#include "unicode/uchar.h"
#include "cstring.h"
#include "ucol_tok.h"
#include "tscoll.h"
#include "dadrcoll.h"
DataDrivenCollatorTest::DataDrivenCollatorTest()
: seq(StringCharacterIterator(""))
{
UErrorCode status = U_ZERO_ERROR;
TestLog testLog;
driver = TestDataModule::getTestDataModule("DataDrivenCollationTest", testLog, status);
}
DataDrivenCollatorTest::~DataDrivenCollatorTest()
{
delete driver;
}
void DataDrivenCollatorTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */)
{
if(driver != NULL) {
if (exec)
{
logln("TestSuite Collator: ");
}
UErrorCode status = U_ZERO_ERROR;
const DataMap *info = NULL;
TestData *testData = driver->createTestData(index, status);
if(U_SUCCESS(status)) {
name = testData->getName();
if(testData->getInfo(info, status)) {
log(info->getString("Description", status));
}
if(exec) {
log(name);
logln("---");
logln("");
processTest(testData, status);
}
delete testData;
} else {
name = "";
}
} else {
errln("collate/DataDrivenTest data not initialized!");
name = "";
}
}
UBool
DataDrivenCollatorTest::setTestSequence(const UnicodeString &setSequence, UnicodeString &source, Collator::EComparisonResult &relation, UErrorCode &status) {
seq.setText(setSequence);
return getNextInSequence(source, relation, status);
}
// Parses the sequence to be tested
UBool
DataDrivenCollatorTest::getNextInSequence(UnicodeString &source, Collator::EComparisonResult &relation, UErrorCode &status) {
source.truncate(0);
// TODO: add quoting support - will need it pretty soon!
UBool quoted = FALSE;
UBool quotedsingle = FALSE;
UChar32 currChar = 0;
while(currChar != CharacterIterator::DONE) {
currChar= seq.next32PostInc();
if(!quoted) {
if(u_isWhitespace(currChar)) {
continue;
}
switch(currChar) {
case CharacterIterator::DONE:
break;
case 0x003C /* < */:
relation = Collator::LESS;
currChar = CharacterIterator::DONE;
break;
case 0x003D /* = */:
relation = Collator::EQUAL;
currChar = CharacterIterator::DONE;
break;
case 0x003E /* > */:
relation = Collator::GREATER;
currChar = CharacterIterator::DONE;
break;
case 0x0027 /* ' */: /* very basic quoting */
quoted = TRUE;
quotedsingle = FALSE;
break;
case 0x005c /* \ */: /* single quote */
quoted = TRUE;
quotedsingle = TRUE;
break;
default:
source.append(currChar);
}
} else {
if(currChar == CharacterIterator::DONE) {
status = U_ILLEGAL_ARGUMENT_ERROR;
errln("Quote in sequence not closed!");
return FALSE;
} else if(currChar == 0x0027) {
quoted = FALSE;
} else {
source.append(currChar);
}
if(quotedsingle) {
quoted = FALSE;
}
}
}
return seq.hasNext();
}
// Reads the options string and sets appropriate attributes in collator
void
DataDrivenCollatorTest::processArguments(Collator *col, const UChar *start, int32_t optLen, UErrorCode &status) {
const UChar *end = start+optLen;
UColAttribute attrib;
UColAttributeValue value;
if(optLen == 0) {
return;
}
start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status);
while(start != NULL) {
if(U_SUCCESS(status)) {
col->setAttribute(attrib, value, status);
}
start = ucol_tok_getNextArgument(start, end, &attrib, &value, &status);
}
}
void
DataDrivenCollatorTest::processTest(TestData *testData, UErrorCode &status) {
Collator *col = NULL;
/*
UnicodeString testInit[256];
const char **testNames = new const char*[256];
int32_t settingsSetSize = 0;
const UChar *arguments = NULL;
int32_t argLen = 0;
int32_t i = 0;
while(settingsSetSize = driver->getNextSettingsSet(testNames, testInit, 256, status)) {
argLen = 0;
for(i = 0; i < settingsSetSize; i++) {
if(strcmp(testNames[i], "Locale") == 0) { // Make the locale dependent collator
if(col == NULL) {
char localeName[256];
testInit[i].extract(0, testInit[i].length(), localeName, "");
col = Collator::createInstance(localeName, status);
if(U_SUCCESS(status)) {
logln("Testing collator for locale "+testInit[i]);
} else {
errln("Unable to instantiate collator for locale "+testInit[i]);
return;
}
} else {
errln("Collator defined more than once!");
return;
}
} else if(strcmp(testNames[i], "Rules") == 0) {
if(col == NULL) {
col = new RuleBasedCollator(testInit[i], status);
if(U_SUCCESS(status)) {
logln("Testing collator for rules "+UnicodeString(testInit[i]));
} else {
errln("Unable to instantiate collator for rules "+UnicodeString(testInit[i]));
return;
}
} else {
errln("Collator defined more than once!");
return;
}
} else if(strcmp(testNames[i], "Attributes") == 0) {
logln("Arguments: "+testInit[i]);
argLen = testInit[i].length();
arguments = testInit[i].getBuffer();
} else {
errln("I don't understand the setting "+UnicodeString(testNames[i]));
}
}
if(col != NULL) {
if(argLen > 0) {
processArguments(col, arguments, argLen, status);
if(U_SUCCESS(status)) {
UnicodeString sequence[1];
while(driver->getNextTestCase(sequence, 1, status)) {
processSequence(col, *sequence, status);
}
} else {
errln("Couldn't process arguments");
}
}
} else {
errln("Couldn't instantiate a collator!");
}
delete col;
}
delete testNames;
*/
const UChar *arguments = NULL;
int32_t argLen = 0;
const DataMap *settings = NULL;
const DataMap *currentCase = NULL;
UErrorCode intStatus = U_ZERO_ERROR;
UnicodeString testSetting;
while(testData->nextSettings(settings, status)) {
intStatus = U_ZERO_ERROR;
// try to get a locale
testSetting = settings->getString("TestLocale", intStatus);
if(U_SUCCESS(intStatus)) {
char localeName[256];
testSetting.extract(0, testSetting.length(), localeName, "");
col = Collator::createInstance(localeName, status);
if(U_SUCCESS(status)) {
logln("Testing collator for locale "+testSetting);
} else {
errln("Unable to instantiate collator for locale "+testSetting);
return;
}
} else {
// if no locale, try from rules
intStatus = U_ZERO_ERROR;
testSetting = settings->getString("Rules", intStatus);
if(U_SUCCESS(intStatus)) {
col = new RuleBasedCollator(testSetting, status);
UCollator *ucol = ucol_openRules(testSetting.getBuffer(), testSetting.length(), UCOL_DEFAULT, UCOL_DEFAULT, NULL, &status);
if(U_SUCCESS(status)) {
logln("Testing collator for rules "+testSetting);
} else {
errln("Unable to instantiate collator for rules "+testSetting);
return;
}
} else {
errln("No collator definition!");
}
}
if(col != NULL) {
// get attributes
testSetting = settings->getString("Arguments", intStatus);
if(U_SUCCESS(intStatus)) {
logln("Arguments: "+testSetting);
argLen = testSetting.length();
arguments = testSetting.getBuffer();
processArguments(col, arguments, argLen, intStatus);
if(U_FAILURE(intStatus)) {
errln("Couldn't process arguments");
break;
}
} else {
intStatus = U_ZERO_ERROR;
}
// Start the processing
while(testData->nextCase(currentCase, status)) {
UnicodeString sequence = currentCase->getString("sequence", status);
if(U_SUCCESS(status)) {
processSequence(col, sequence, status);
}
}
} else {
errln("Couldn't instantiate a collator!");
}
delete col;
col = NULL;
}
}
void
DataDrivenCollatorTest::processSequence(Collator* col, const UnicodeString &sequence, UErrorCode &status) {
UnicodeString source;
UnicodeString target;
UnicodeString temp;
Collator::EComparisonResult relation = Collator::EQUAL;
Collator::EComparisonResult nextRelation = Collator::EQUAL;
UBool hasNext;
setTestSequence(sequence, 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;
relation = nextRelation;
} while(hasNext);
}