/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2010, 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"
#if !UCONFIG_NO_COLLATION && !UCONFIG_NO_FILE_IO
#include "unicode/uchar.h"
#include "unicode/tstdtmod.h"
#include "cstring.h"
#include "ucol_tok.h"
#include "tscoll.h"
#include "dadrcoll.h"
U_CDECL_BEGIN
static void U_CALLCONV deleteSeqElement(void *elem) {
delete((SeqElement *)elem);
}
U_CDECL_END
DataDrivenCollatorTest::DataDrivenCollatorTest()
: seq(StringCharacterIterator("")),
status(U_ZERO_ERROR),
sequences(status)
{
driver = TestDataModule::getTestDataModule("DataDrivenCollationTest", *this, status);
sequences.setDeleter(deleteSeqElement);
UCA = (RuleBasedCollator*)Collator::createInstance("root", status);
}
DataDrivenCollatorTest::~DataDrivenCollatorTest()
{
delete driver;
delete UCA;
}
void DataDrivenCollatorTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par */)
{
if(driver != NULL) {
if (exec)
{
logln("TestSuite Collator: ");
}
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);
}
delete testData;
} else {
name = "";
}
} else {
dataerrln("collate/DataDrivenTest data not initialized!");
name = "";
}
}
UBool
DataDrivenCollatorTest::setTestSequence(const UnicodeString &setSequence, SeqElement &el) {
seq.setText(setSequence);
return getNextInSequence(el);
}
// Parses the sequence to be tested
UBool
DataDrivenCollatorTest::getNextInSequence(SeqElement &el) {
el.source.truncate(0);
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 /* < */:
el.relation = Collator::LESS;
currChar = CharacterIterator::DONE;
break;
case 0x003D /* = */:
el.relation = Collator::EQUAL;
currChar = CharacterIterator::DONE;
break;
case 0x003E /* > */:
el.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:
el.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 {
el.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) {
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) {
Collator *col = NULL;
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);
if(U_SUCCESS(status)) {
logln("Testing collator for rules "+testSetting);
} else {
errln("Unable to instantiate collator for rules "+testSetting+" - "+u_errorName(status));
return;
}
} else {
errln("No collator definition!");
return;
}
}
int32_t cloneSize = 0;
uint8_t* cloneBuf = NULL;
RuleBasedCollator* clone = NULL;
if(col != NULL){
RuleBasedCollator* rbc = (RuleBasedCollator*)col;
cloneSize = rbc->cloneBinary(NULL, 0, intStatus);
intStatus = U_ZERO_ERROR;
cloneBuf = (uint8_t*) malloc(cloneSize);
cloneSize = rbc->cloneBinary(cloneBuf, cloneSize, intStatus);
clone = new RuleBasedCollator(cloneBuf, cloneSize, UCA, intStatus);
if(U_FAILURE(intStatus)){
errln("Could not clone the RuleBasedCollator. Error: %s", u_errorName(intStatus));
intStatus= U_ZERO_ERROR;
}
// get attributes
testSetting = settings->getString("Arguments", intStatus);
if(U_SUCCESS(intStatus)) {
logln("Arguments: "+testSetting);
argLen = testSetting.length();
arguments = testSetting.getBuffer();
processArguments(col, arguments, argLen);
if(clone != NULL){
processArguments(clone, arguments, argLen);
}
if(U_FAILURE(status)) {
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);
if(clone != NULL){
processSequence(clone, sequence);
}
}
}
} else {
errln("Couldn't instantiate a collator!");
}
delete clone;
free(cloneBuf);
delete col;
col = NULL;
}
}
void
DataDrivenCollatorTest::processSequence(Collator* col, const UnicodeString &sequence) {
Collator::EComparisonResult relation = Collator::EQUAL;
UBool hasNext;
SeqElement *source = NULL;
SeqElement *target = NULL;
int32_t j = 0;
sequences.removeAllElements();
target = new SeqElement();
setTestSequence(sequence, *target);
sequences.addElement(target, status);
do {
relation = Collator::EQUAL;
target = new SeqElement();
hasNext = getNextInSequence(*target);
for(j = sequences.size(); j > 0; j--) {
source = (SeqElement *)sequences.elementAt(j-1);
if(relation == Collator::EQUAL && source->relation != Collator::EQUAL) {
relation = source->relation;
}
doTest(col, source->source, target->source, relation);
}
sequences.addElement(target, status);
source = target;
} while(hasNext);
}
#endif /* #if !UCONFIG_NO_COLLATION */